174a4d8c2SCharles.Forsyth #include "u.h"
274a4d8c2SCharles.Forsyth #include "../port/lib.h"
374a4d8c2SCharles.Forsyth #include "mem.h"
474a4d8c2SCharles.Forsyth #include "dat.h"
574a4d8c2SCharles.Forsyth #include "fns.h"
674a4d8c2SCharles.Forsyth #include "../port/error.h"
774a4d8c2SCharles.Forsyth #include <isa.h>
874a4d8c2SCharles.Forsyth #include <interp.h>
974a4d8c2SCharles.Forsyth #include <kernel.h>
1074a4d8c2SCharles.Forsyth #include "raise.h"
1174a4d8c2SCharles.Forsyth
1274a4d8c2SCharles.Forsyth void vmachine(void*);
1374a4d8c2SCharles.Forsyth
1474a4d8c2SCharles.Forsyth struct
1574a4d8c2SCharles.Forsyth {
1674a4d8c2SCharles.Forsyth Lock l;
1774a4d8c2SCharles.Forsyth Prog* runhd;
1874a4d8c2SCharles.Forsyth Prog* runtl;
1974a4d8c2SCharles.Forsyth Prog* head;
2074a4d8c2SCharles.Forsyth Prog* tail;
2174a4d8c2SCharles.Forsyth Rendez irend;
2274a4d8c2SCharles.Forsyth int idle;
2374a4d8c2SCharles.Forsyth int nyield;
2474a4d8c2SCharles.Forsyth int creating;
2574a4d8c2SCharles.Forsyth Proc* vmq; /* queue of procs wanting vm */
2674a4d8c2SCharles.Forsyth Proc* vmqt;
2774a4d8c2SCharles.Forsyth Proc* idlevmq; /* queue of procs wanting work */
2874a4d8c2SCharles.Forsyth Atidle* idletasks;
2974a4d8c2SCharles.Forsyth } isched;
3074a4d8c2SCharles.Forsyth
3174a4d8c2SCharles.Forsyth int bflag;
3274a4d8c2SCharles.Forsyth int cflag;
3374a4d8c2SCharles.Forsyth uvlong gcbusy;
3474a4d8c2SCharles.Forsyth uvlong gcidle;
3574a4d8c2SCharles.Forsyth uvlong gcidlepass;
3674a4d8c2SCharles.Forsyth uvlong gcpartial;
3774a4d8c2SCharles.Forsyth int keepbroken = 1;
3874a4d8c2SCharles.Forsyth static Prog* proghash[64];
3974a4d8c2SCharles.Forsyth
4074a4d8c2SCharles.Forsyth static Progs* delgrp(Prog*);
4174a4d8c2SCharles.Forsyth static void addgrp(Prog*, Prog*);
4274a4d8c2SCharles.Forsyth void printgrp(Prog*, char*);
4374a4d8c2SCharles.Forsyth
4474a4d8c2SCharles.Forsyth static Prog**
pidlook(int pid)4574a4d8c2SCharles.Forsyth pidlook(int pid)
4674a4d8c2SCharles.Forsyth {
4774a4d8c2SCharles.Forsyth ulong h;
4874a4d8c2SCharles.Forsyth Prog **l;
4974a4d8c2SCharles.Forsyth
5074a4d8c2SCharles.Forsyth h = (ulong)pid % nelem(proghash);
5174a4d8c2SCharles.Forsyth for(l = &proghash[h]; *l != nil && (*l)->pid != pid; l = &(*l)->pidlink)
5274a4d8c2SCharles.Forsyth ;
5374a4d8c2SCharles.Forsyth return l;
5474a4d8c2SCharles.Forsyth }
5574a4d8c2SCharles.Forsyth
5674a4d8c2SCharles.Forsyth int
tready(void * a)5774a4d8c2SCharles.Forsyth tready(void *a)
5874a4d8c2SCharles.Forsyth {
5974a4d8c2SCharles.Forsyth USED(a);
6074a4d8c2SCharles.Forsyth return isched.runhd != nil || isched.vmq != nil;
6174a4d8c2SCharles.Forsyth }
6274a4d8c2SCharles.Forsyth
6374a4d8c2SCharles.Forsyth Prog*
progpid(int pid)6474a4d8c2SCharles.Forsyth progpid(int pid)
6574a4d8c2SCharles.Forsyth {
6674a4d8c2SCharles.Forsyth return *pidlook(pid);
6774a4d8c2SCharles.Forsyth }
6874a4d8c2SCharles.Forsyth
6974a4d8c2SCharles.Forsyth Prog*
progn(int n)7074a4d8c2SCharles.Forsyth progn(int n)
7174a4d8c2SCharles.Forsyth {
7274a4d8c2SCharles.Forsyth Prog *p;
7374a4d8c2SCharles.Forsyth
7474a4d8c2SCharles.Forsyth for(p = isched.head; p && n--; p = p->next)
7574a4d8c2SCharles.Forsyth ;
7674a4d8c2SCharles.Forsyth return p;
7774a4d8c2SCharles.Forsyth }
7874a4d8c2SCharles.Forsyth
7974a4d8c2SCharles.Forsyth int
nprog(void)8074a4d8c2SCharles.Forsyth nprog(void)
8174a4d8c2SCharles.Forsyth {
8274a4d8c2SCharles.Forsyth int n;
8374a4d8c2SCharles.Forsyth Prog *p;
8474a4d8c2SCharles.Forsyth
8574a4d8c2SCharles.Forsyth n = 0;
8674a4d8c2SCharles.Forsyth for(p = isched.head; p; p = p->next)
8774a4d8c2SCharles.Forsyth n++;
8874a4d8c2SCharles.Forsyth return n;
8974a4d8c2SCharles.Forsyth }
9074a4d8c2SCharles.Forsyth
9174a4d8c2SCharles.Forsyth static void
accountant(void)9274a4d8c2SCharles.Forsyth accountant(void)
9374a4d8c2SCharles.Forsyth {
9474a4d8c2SCharles.Forsyth Prog *p;
9574a4d8c2SCharles.Forsyth
9674a4d8c2SCharles.Forsyth p = isched.runhd;
9774a4d8c2SCharles.Forsyth if(p != nil)
9874a4d8c2SCharles.Forsyth p->ticks++;
9974a4d8c2SCharles.Forsyth }
10074a4d8c2SCharles.Forsyth
10174a4d8c2SCharles.Forsyth static void
execatidle(void)10274a4d8c2SCharles.Forsyth execatidle(void)
10374a4d8c2SCharles.Forsyth {
10474a4d8c2SCharles.Forsyth int done;
10574a4d8c2SCharles.Forsyth
10674a4d8c2SCharles.Forsyth if(tready(nil))
10774a4d8c2SCharles.Forsyth return;
10874a4d8c2SCharles.Forsyth
10974a4d8c2SCharles.Forsyth gcidle++;
11074a4d8c2SCharles.Forsyth up->type = IdleGC;
11174a4d8c2SCharles.Forsyth up->iprog = nil;
11274a4d8c2SCharles.Forsyth addrun(up->prog);
11374a4d8c2SCharles.Forsyth
11474a4d8c2SCharles.Forsyth done = gccolor+3;
11574a4d8c2SCharles.Forsyth while(gccolor < done && gcruns()) {
11674a4d8c2SCharles.Forsyth if(isched.vmq != nil || isched.runhd != isched.runtl) {
11774a4d8c2SCharles.Forsyth gcpartial++;
11874a4d8c2SCharles.Forsyth break;
11974a4d8c2SCharles.Forsyth }
12074a4d8c2SCharles.Forsyth rungc(isched.head);
12174a4d8c2SCharles.Forsyth gcidlepass++;
122*112f90aeSforsyth if(((ulong)gcidlepass&0xFF) == 0)
12374a4d8c2SCharles.Forsyth sched();
12474a4d8c2SCharles.Forsyth }
12574a4d8c2SCharles.Forsyth
12674a4d8c2SCharles.Forsyth up->type = Interp;
12774a4d8c2SCharles.Forsyth delrunq(up->prog);
12874a4d8c2SCharles.Forsyth }
12974a4d8c2SCharles.Forsyth
13074a4d8c2SCharles.Forsyth Prog*
newprog(Prog * p,Modlink * m)13174a4d8c2SCharles.Forsyth newprog(Prog *p, Modlink *m)
13274a4d8c2SCharles.Forsyth {
13374a4d8c2SCharles.Forsyth Heap *h;
13474a4d8c2SCharles.Forsyth Prog *n, **ph;
13574a4d8c2SCharles.Forsyth Osenv *on, *op;
13674a4d8c2SCharles.Forsyth static int pidnum;
13774a4d8c2SCharles.Forsyth
138d3ba796fSCharles.Forsyth if(p != nil){
139d3ba796fSCharles.Forsyth if(p->group != nil)
140d3ba796fSCharles.Forsyth p->flags |= p->group->flags & Pkilled;
141d3ba796fSCharles.Forsyth if(p->kill != nil)
142d3ba796fSCharles.Forsyth error(p->kill);
143d3ba796fSCharles.Forsyth if(p->flags & Pkilled)
144d3ba796fSCharles.Forsyth error("");
145d3ba796fSCharles.Forsyth }
14674a4d8c2SCharles.Forsyth n = malloc(sizeof(Prog)+sizeof(Osenv));
14774a4d8c2SCharles.Forsyth if(n == 0){
14874a4d8c2SCharles.Forsyth if(p == nil)
14974a4d8c2SCharles.Forsyth panic("no memory");
15074a4d8c2SCharles.Forsyth else
15174a4d8c2SCharles.Forsyth error(exNomem);
15274a4d8c2SCharles.Forsyth }
15374a4d8c2SCharles.Forsyth
15474a4d8c2SCharles.Forsyth n->pid = ++pidnum;
15574a4d8c2SCharles.Forsyth if(n->pid <= 0)
15674a4d8c2SCharles.Forsyth panic("no pids");
15774a4d8c2SCharles.Forsyth n->group = nil;
15874a4d8c2SCharles.Forsyth
15974a4d8c2SCharles.Forsyth if(isched.tail != nil) {
16074a4d8c2SCharles.Forsyth n->prev = isched.tail;
16174a4d8c2SCharles.Forsyth isched.tail->next = n;
16274a4d8c2SCharles.Forsyth }
16374a4d8c2SCharles.Forsyth else {
16474a4d8c2SCharles.Forsyth isched.head = n;
16574a4d8c2SCharles.Forsyth n->prev = nil;
16674a4d8c2SCharles.Forsyth }
16774a4d8c2SCharles.Forsyth isched.tail = n;
16874a4d8c2SCharles.Forsyth
16974a4d8c2SCharles.Forsyth ph = pidlook(n->pid);
17074a4d8c2SCharles.Forsyth if(*ph != nil)
17174a4d8c2SCharles.Forsyth panic("dup pid");
17274a4d8c2SCharles.Forsyth n->pidlink = nil;
17374a4d8c2SCharles.Forsyth *ph = n;
17474a4d8c2SCharles.Forsyth
17574a4d8c2SCharles.Forsyth n->osenv = (Osenv*)((uchar*)n + sizeof(Prog));
17674a4d8c2SCharles.Forsyth n->xec = xec;
17774a4d8c2SCharles.Forsyth n->quanta = PQUANTA;
17874a4d8c2SCharles.Forsyth n->flags = 0;
17974a4d8c2SCharles.Forsyth n->exval = H;
18074a4d8c2SCharles.Forsyth
18174a4d8c2SCharles.Forsyth h = D2H(m);
18274a4d8c2SCharles.Forsyth h->ref++;
18374a4d8c2SCharles.Forsyth Setmark(h);
18474a4d8c2SCharles.Forsyth n->R.M = m;
18574a4d8c2SCharles.Forsyth n->R.MP = m->MP;
18674a4d8c2SCharles.Forsyth if(m->MP != H)
18774a4d8c2SCharles.Forsyth Setmark(D2H(m->MP));
18874a4d8c2SCharles.Forsyth addrun(n);
18974a4d8c2SCharles.Forsyth
19074a4d8c2SCharles.Forsyth if(p == nil){
19174a4d8c2SCharles.Forsyth newgrp(n);
19274a4d8c2SCharles.Forsyth return n;
19374a4d8c2SCharles.Forsyth }
19474a4d8c2SCharles.Forsyth
19574a4d8c2SCharles.Forsyth addgrp(n, p);
19674a4d8c2SCharles.Forsyth n->flags = p->flags;
19774a4d8c2SCharles.Forsyth if(p->flags & Prestrict)
19874a4d8c2SCharles.Forsyth n->flags |= Prestricted;
19974a4d8c2SCharles.Forsyth memmove(n->osenv, p->osenv, sizeof(Osenv));
20074a4d8c2SCharles.Forsyth op = p->osenv;
20174a4d8c2SCharles.Forsyth on = n->osenv;
20274a4d8c2SCharles.Forsyth on->waitq = op->childq;
20374a4d8c2SCharles.Forsyth on->childq = nil;
20474a4d8c2SCharles.Forsyth on->debug = nil;
20574a4d8c2SCharles.Forsyth incref(on->pgrp);
20674a4d8c2SCharles.Forsyth incref(on->fgrp);
20774a4d8c2SCharles.Forsyth if(on->egrp != nil)
20874a4d8c2SCharles.Forsyth incref(on->egrp);
20974a4d8c2SCharles.Forsyth if(on->sigs != nil)
21074a4d8c2SCharles.Forsyth incref(on->sigs);
21174a4d8c2SCharles.Forsyth on->user = nil;
21274a4d8c2SCharles.Forsyth kstrdup(&on->user, op->user);
21374a4d8c2SCharles.Forsyth on->errstr = on->errbuf0;
21474a4d8c2SCharles.Forsyth on->syserrstr = on->errbuf1;
21574a4d8c2SCharles.Forsyth
21674a4d8c2SCharles.Forsyth return n;
21774a4d8c2SCharles.Forsyth }
21874a4d8c2SCharles.Forsyth
21974a4d8c2SCharles.Forsyth void
delprog(Prog * p,char * msg)22074a4d8c2SCharles.Forsyth delprog(Prog *p, char *msg)
22174a4d8c2SCharles.Forsyth {
22274a4d8c2SCharles.Forsyth Osenv *o;
22374a4d8c2SCharles.Forsyth Prog **ph;
22474a4d8c2SCharles.Forsyth
22574a4d8c2SCharles.Forsyth tellsomeone(p, msg); /* call before being removed from prog list */
22674a4d8c2SCharles.Forsyth
22774a4d8c2SCharles.Forsyth o = p->osenv;
22874a4d8c2SCharles.Forsyth release();
22974a4d8c2SCharles.Forsyth closepgrp(o->pgrp);
23074a4d8c2SCharles.Forsyth closefgrp(o->fgrp);
23174a4d8c2SCharles.Forsyth closeegrp(o->egrp);
23274a4d8c2SCharles.Forsyth closesigs(o->sigs);
23374a4d8c2SCharles.Forsyth acquire();
23474a4d8c2SCharles.Forsyth
23574a4d8c2SCharles.Forsyth delgrp(p);
23674a4d8c2SCharles.Forsyth
23774a4d8c2SCharles.Forsyth if(p->prev)
23874a4d8c2SCharles.Forsyth p->prev->next = p->next;
23974a4d8c2SCharles.Forsyth else
24074a4d8c2SCharles.Forsyth isched.head = p->next;
24174a4d8c2SCharles.Forsyth
24274a4d8c2SCharles.Forsyth if(p->next)
24374a4d8c2SCharles.Forsyth p->next->prev = p->prev;
24474a4d8c2SCharles.Forsyth else
24574a4d8c2SCharles.Forsyth isched.tail = p->prev;
24674a4d8c2SCharles.Forsyth
24774a4d8c2SCharles.Forsyth ph = pidlook(p->pid);
24874a4d8c2SCharles.Forsyth if(*ph == nil)
24974a4d8c2SCharles.Forsyth panic("lost pid");
25074a4d8c2SCharles.Forsyth *ph = p->pidlink;
25174a4d8c2SCharles.Forsyth
25274a4d8c2SCharles.Forsyth if(p == isched.runhd) {
25374a4d8c2SCharles.Forsyth isched.runhd = p->link;
25474a4d8c2SCharles.Forsyth if(p->link == nil)
25574a4d8c2SCharles.Forsyth isched.runtl = nil;
25674a4d8c2SCharles.Forsyth }
25774a4d8c2SCharles.Forsyth p->state = 0xdeadbeef;
25874a4d8c2SCharles.Forsyth free(o->user);
25974a4d8c2SCharles.Forsyth free(p->killstr);
26074a4d8c2SCharles.Forsyth free(p->exstr);
26174a4d8c2SCharles.Forsyth free(p);
26274a4d8c2SCharles.Forsyth }
26374a4d8c2SCharles.Forsyth
26474a4d8c2SCharles.Forsyth void
renameproguser(char * old,char * new)26574a4d8c2SCharles.Forsyth renameproguser(char *old, char *new)
26674a4d8c2SCharles.Forsyth {
26774a4d8c2SCharles.Forsyth Prog *p;
26874a4d8c2SCharles.Forsyth Osenv *o;
26974a4d8c2SCharles.Forsyth
27074a4d8c2SCharles.Forsyth acquire();
27174a4d8c2SCharles.Forsyth for(p = isched.head; p; p = p->next){
27274a4d8c2SCharles.Forsyth o = p->osenv;
27374a4d8c2SCharles.Forsyth if(o->user != nil && strcmp(o->user, old) == 0)
27474a4d8c2SCharles.Forsyth kstrdup(&o->user, new);
27574a4d8c2SCharles.Forsyth }
27674a4d8c2SCharles.Forsyth release();
27774a4d8c2SCharles.Forsyth }
27874a4d8c2SCharles.Forsyth
27974a4d8c2SCharles.Forsyth void
tellsomeone(Prog * p,char * buf)28074a4d8c2SCharles.Forsyth tellsomeone(Prog *p, char *buf)
28174a4d8c2SCharles.Forsyth {
28274a4d8c2SCharles.Forsyth Osenv *o;
28374a4d8c2SCharles.Forsyth
28474a4d8c2SCharles.Forsyth if(waserror())
28574a4d8c2SCharles.Forsyth return;
28674a4d8c2SCharles.Forsyth o = p->osenv;
28774a4d8c2SCharles.Forsyth if(o->childq != nil)
28874a4d8c2SCharles.Forsyth qproduce(o->childq, buf, strlen(buf));
28974a4d8c2SCharles.Forsyth if(o->waitq != nil)
29074a4d8c2SCharles.Forsyth qproduce(o->waitq, buf, strlen(buf));
29174a4d8c2SCharles.Forsyth poperror();
29274a4d8c2SCharles.Forsyth }
29374a4d8c2SCharles.Forsyth
29474a4d8c2SCharles.Forsyth static void
swiprog(Prog * p)29574a4d8c2SCharles.Forsyth swiprog(Prog *p)
29674a4d8c2SCharles.Forsyth {
29774a4d8c2SCharles.Forsyth Proc *q, *eq;
29874a4d8c2SCharles.Forsyth
29974a4d8c2SCharles.Forsyth q = proctab(0);
30074a4d8c2SCharles.Forsyth for(eq = q+conf.nproc; q < eq; q++) {
30174a4d8c2SCharles.Forsyth if(q->iprog == p) {
30274a4d8c2SCharles.Forsyth swiproc(q, 1);
30374a4d8c2SCharles.Forsyth return;
30474a4d8c2SCharles.Forsyth }
30574a4d8c2SCharles.Forsyth }
30674a4d8c2SCharles.Forsyth /*print("didn't find\n");*/
30774a4d8c2SCharles.Forsyth }
30874a4d8c2SCharles.Forsyth
30974a4d8c2SCharles.Forsyth static Prog*
grpleader(Prog * p)31074a4d8c2SCharles.Forsyth grpleader(Prog *p)
31174a4d8c2SCharles.Forsyth {
31274a4d8c2SCharles.Forsyth Progs *g;
31374a4d8c2SCharles.Forsyth Prog *l;
31474a4d8c2SCharles.Forsyth
31574a4d8c2SCharles.Forsyth g = p->group;
31674a4d8c2SCharles.Forsyth if(g != nil && (l = g->head) != nil && l->pid == g->id)
31774a4d8c2SCharles.Forsyth return l;
31874a4d8c2SCharles.Forsyth return nil;
31974a4d8c2SCharles.Forsyth }
32074a4d8c2SCharles.Forsyth
32174a4d8c2SCharles.Forsyth int
exprog(Prog * p,char * exc)32274a4d8c2SCharles.Forsyth exprog(Prog *p, char *exc)
32374a4d8c2SCharles.Forsyth {
32474a4d8c2SCharles.Forsyth switch(p->state) {
32574a4d8c2SCharles.Forsyth case Palt:
32674a4d8c2SCharles.Forsyth altdone(p->R.s, p, nil, -1);
32774a4d8c2SCharles.Forsyth break;
32874a4d8c2SCharles.Forsyth case Psend:
32974a4d8c2SCharles.Forsyth cqdelp(&p->chan->send, p);
33074a4d8c2SCharles.Forsyth break;
33174a4d8c2SCharles.Forsyth case Precv:
33274a4d8c2SCharles.Forsyth cqdelp(&p->chan->recv, p);
33374a4d8c2SCharles.Forsyth break;
33474a4d8c2SCharles.Forsyth case Pready:
33574a4d8c2SCharles.Forsyth break;
33674a4d8c2SCharles.Forsyth case Prelease:
33774a4d8c2SCharles.Forsyth swiprog(p);
33874a4d8c2SCharles.Forsyth break;
33974a4d8c2SCharles.Forsyth case Pexiting:
34074a4d8c2SCharles.Forsyth case Pbroken:
34174a4d8c2SCharles.Forsyth case Pdebug:
34274a4d8c2SCharles.Forsyth return 0;
34374a4d8c2SCharles.Forsyth default:
34474a4d8c2SCharles.Forsyth panic("exprog - bad state 0x%x\n", p->state);
34574a4d8c2SCharles.Forsyth }
34674a4d8c2SCharles.Forsyth if(p->state != Pready && p->state != Prelease)
34774a4d8c2SCharles.Forsyth addrun(p);
34874a4d8c2SCharles.Forsyth if(p->kill == nil){
34974a4d8c2SCharles.Forsyth if(p->killstr == nil){
35074a4d8c2SCharles.Forsyth p->killstr = malloc(ERRMAX);
35174a4d8c2SCharles.Forsyth if(p->killstr == nil){
35274a4d8c2SCharles.Forsyth p->kill = Enomem;
35374a4d8c2SCharles.Forsyth return 1;
35474a4d8c2SCharles.Forsyth }
35574a4d8c2SCharles.Forsyth }
35674a4d8c2SCharles.Forsyth kstrcpy(p->killstr, exc, ERRMAX);
35774a4d8c2SCharles.Forsyth p->kill = p->killstr;
35874a4d8c2SCharles.Forsyth }
35974a4d8c2SCharles.Forsyth return 1;
36074a4d8c2SCharles.Forsyth }
36174a4d8c2SCharles.Forsyth
36274a4d8c2SCharles.Forsyth static void
propex(Prog * p,char * estr)36374a4d8c2SCharles.Forsyth propex(Prog *p, char *estr)
36474a4d8c2SCharles.Forsyth {
36574a4d8c2SCharles.Forsyth Prog *f, *nf, *pgl;
36674a4d8c2SCharles.Forsyth
36774a4d8c2SCharles.Forsyth if(!(p->flags & (Ppropagate|Pnotifyleader)) || p->group == nil)
36874a4d8c2SCharles.Forsyth return;
36974a4d8c2SCharles.Forsyth if(*estr == 0){
37074a4d8c2SCharles.Forsyth if((p->flags & Pkilled) == 0)
37174a4d8c2SCharles.Forsyth return;
37274a4d8c2SCharles.Forsyth estr = "killed";
37374a4d8c2SCharles.Forsyth }
37474a4d8c2SCharles.Forsyth pgl = grpleader(p);
37574a4d8c2SCharles.Forsyth if(pgl == nil)
37674a4d8c2SCharles.Forsyth pgl = p;
37774a4d8c2SCharles.Forsyth if(!(pgl->flags & (Ppropagate|Pnotifyleader)))
37874a4d8c2SCharles.Forsyth return; /* exceptions are local; don't propagate */
37974a4d8c2SCharles.Forsyth for(f = p->group->head; f != nil; f = nf){
38074a4d8c2SCharles.Forsyth nf = f->grpnext;
38174a4d8c2SCharles.Forsyth if(f != p && f != pgl){
38274a4d8c2SCharles.Forsyth if(pgl->flags & Ppropagate)
38374a4d8c2SCharles.Forsyth exprog(f, estr);
38474a4d8c2SCharles.Forsyth else{
38574a4d8c2SCharles.Forsyth f->flags &= ~(Ppropagate|Pnotifyleader); /* prevent recursion */
38674a4d8c2SCharles.Forsyth killprog(f, "killed");
38774a4d8c2SCharles.Forsyth }
38874a4d8c2SCharles.Forsyth }
38974a4d8c2SCharles.Forsyth }
39074a4d8c2SCharles.Forsyth if(p != pgl)
39174a4d8c2SCharles.Forsyth exprog(pgl, estr);
39274a4d8c2SCharles.Forsyth }
39374a4d8c2SCharles.Forsyth
39474a4d8c2SCharles.Forsyth int
killprog(Prog * p,char * cause)39574a4d8c2SCharles.Forsyth killprog(Prog *p, char *cause)
39674a4d8c2SCharles.Forsyth {
39774a4d8c2SCharles.Forsyth Osenv *env;
39874a4d8c2SCharles.Forsyth char msg[ERRMAX+2*KNAMELEN];
39974a4d8c2SCharles.Forsyth
40074a4d8c2SCharles.Forsyth if(p == isched.runhd) {
40174a4d8c2SCharles.Forsyth p->kill = "";
40274a4d8c2SCharles.Forsyth p->flags |= Pkilled;
40374a4d8c2SCharles.Forsyth p->state = Pexiting;
40474a4d8c2SCharles.Forsyth return 0;
40574a4d8c2SCharles.Forsyth }
40674a4d8c2SCharles.Forsyth
40774a4d8c2SCharles.Forsyth switch(p->state) {
40874a4d8c2SCharles.Forsyth case Palt:
40974a4d8c2SCharles.Forsyth altdone(p->R.s, p, nil, -1);
41074a4d8c2SCharles.Forsyth break;
41174a4d8c2SCharles.Forsyth case Psend:
41274a4d8c2SCharles.Forsyth cqdelp(&p->chan->send, p);
41374a4d8c2SCharles.Forsyth break;
41474a4d8c2SCharles.Forsyth case Precv:
41574a4d8c2SCharles.Forsyth cqdelp(&p->chan->recv, p);
41674a4d8c2SCharles.Forsyth break;
41774a4d8c2SCharles.Forsyth case Pready:
41874a4d8c2SCharles.Forsyth delrunq(p);
41974a4d8c2SCharles.Forsyth break;
42074a4d8c2SCharles.Forsyth case Prelease:
42174a4d8c2SCharles.Forsyth p->kill = "";
42274a4d8c2SCharles.Forsyth p->flags |= Pkilled;
42374a4d8c2SCharles.Forsyth p->state = Pexiting;
42474a4d8c2SCharles.Forsyth swiprog(p);
42574a4d8c2SCharles.Forsyth /* No break */
42674a4d8c2SCharles.Forsyth case Pexiting:
42774a4d8c2SCharles.Forsyth return 0;
42874a4d8c2SCharles.Forsyth case Pbroken:
42974a4d8c2SCharles.Forsyth case Pdebug:
43074a4d8c2SCharles.Forsyth break;
43174a4d8c2SCharles.Forsyth default:
43274a4d8c2SCharles.Forsyth panic("killprog - bad state 0x%x\n", p->state);
43374a4d8c2SCharles.Forsyth }
43474a4d8c2SCharles.Forsyth
43574a4d8c2SCharles.Forsyth if(p->addrun != nil) {
43674a4d8c2SCharles.Forsyth p->kill = "";
43774a4d8c2SCharles.Forsyth p->flags |= Pkilled;
43874a4d8c2SCharles.Forsyth p->addrun(p);
43974a4d8c2SCharles.Forsyth p->addrun = nil;
44074a4d8c2SCharles.Forsyth return 0;
44174a4d8c2SCharles.Forsyth }
44274a4d8c2SCharles.Forsyth
44374a4d8c2SCharles.Forsyth env = p->osenv;
44474a4d8c2SCharles.Forsyth if(env->debug != nil) {
44574a4d8c2SCharles.Forsyth p->state = Pbroken;
44674a4d8c2SCharles.Forsyth dbgexit(p, 0, cause);
44774a4d8c2SCharles.Forsyth return 0;
44874a4d8c2SCharles.Forsyth }
44974a4d8c2SCharles.Forsyth
45074a4d8c2SCharles.Forsyth propex(p, "killed");
45174a4d8c2SCharles.Forsyth
45274a4d8c2SCharles.Forsyth snprint(msg, sizeof(msg), "%d \"%s\":%s", p->pid, p->R.M->m->name, cause);
45374a4d8c2SCharles.Forsyth
45474a4d8c2SCharles.Forsyth p->state = Pexiting;
45574a4d8c2SCharles.Forsyth gclock();
45674a4d8c2SCharles.Forsyth destroystack(&p->R);
45774a4d8c2SCharles.Forsyth delprog(p, msg);
45874a4d8c2SCharles.Forsyth gcunlock();
45974a4d8c2SCharles.Forsyth
46074a4d8c2SCharles.Forsyth return 1;
46174a4d8c2SCharles.Forsyth }
46274a4d8c2SCharles.Forsyth
46374a4d8c2SCharles.Forsyth void
newgrp(Prog * p)46474a4d8c2SCharles.Forsyth newgrp(Prog *p)
46574a4d8c2SCharles.Forsyth {
46674a4d8c2SCharles.Forsyth Progs *pg, *g;
46774a4d8c2SCharles.Forsyth
46874a4d8c2SCharles.Forsyth if(p->group != nil && p->group->id == p->pid)
46974a4d8c2SCharles.Forsyth return;
47074a4d8c2SCharles.Forsyth g = malloc(sizeof(*g));
47174a4d8c2SCharles.Forsyth if(g == nil)
47274a4d8c2SCharles.Forsyth error(Enomem);
47374a4d8c2SCharles.Forsyth p->flags &= ~(Ppropagate|Pnotifyleader);
47474a4d8c2SCharles.Forsyth g->id = p->pid;
47574a4d8c2SCharles.Forsyth g->flags = 0;
47674a4d8c2SCharles.Forsyth g->child = nil;
47774a4d8c2SCharles.Forsyth pg = delgrp(p);
47874a4d8c2SCharles.Forsyth g->head = g->tail = p;
47974a4d8c2SCharles.Forsyth p->group = g;
48074a4d8c2SCharles.Forsyth if(pg != nil){
48174a4d8c2SCharles.Forsyth g->sib = pg->child;
48274a4d8c2SCharles.Forsyth pg->child = g;
48374a4d8c2SCharles.Forsyth }
48474a4d8c2SCharles.Forsyth g->parent = pg;
48574a4d8c2SCharles.Forsyth }
48674a4d8c2SCharles.Forsyth
48774a4d8c2SCharles.Forsyth static void
addgrp(Prog * n,Prog * p)48874a4d8c2SCharles.Forsyth addgrp(Prog *n, Prog *p)
48974a4d8c2SCharles.Forsyth {
49074a4d8c2SCharles.Forsyth Progs *g;
49174a4d8c2SCharles.Forsyth
49274a4d8c2SCharles.Forsyth n->group = p->group;
49374a4d8c2SCharles.Forsyth if((g = n->group) != nil){
49474a4d8c2SCharles.Forsyth n->grpnext = nil;
49574a4d8c2SCharles.Forsyth if(g->head != nil){
49674a4d8c2SCharles.Forsyth n->grpprev = g->tail;
49774a4d8c2SCharles.Forsyth g->tail->grpnext = n;
49874a4d8c2SCharles.Forsyth }else{
49974a4d8c2SCharles.Forsyth n->grpprev = nil;
50074a4d8c2SCharles.Forsyth g->head = n;
50174a4d8c2SCharles.Forsyth }
50274a4d8c2SCharles.Forsyth g->tail = n;
50374a4d8c2SCharles.Forsyth }
50474a4d8c2SCharles.Forsyth }
50574a4d8c2SCharles.Forsyth
50674a4d8c2SCharles.Forsyth static Progs*
delgrp(Prog * p)50774a4d8c2SCharles.Forsyth delgrp(Prog *p)
50874a4d8c2SCharles.Forsyth {
50974a4d8c2SCharles.Forsyth Progs *g, *pg, *cg, **l;
51074a4d8c2SCharles.Forsyth
51174a4d8c2SCharles.Forsyth g = p->group;
51274a4d8c2SCharles.Forsyth if(g == nil)
51374a4d8c2SCharles.Forsyth return nil;
51474a4d8c2SCharles.Forsyth if(p->grpprev)
51574a4d8c2SCharles.Forsyth p->grpprev->grpnext = p->grpnext;
51674a4d8c2SCharles.Forsyth else
51774a4d8c2SCharles.Forsyth g->head = p->grpnext;
51874a4d8c2SCharles.Forsyth if(p->grpnext)
51974a4d8c2SCharles.Forsyth p->grpnext->grpprev = p->grpprev;
52074a4d8c2SCharles.Forsyth else
52174a4d8c2SCharles.Forsyth g->tail = p->grpprev;
52274a4d8c2SCharles.Forsyth p->grpprev = p->grpnext = nil;
52374a4d8c2SCharles.Forsyth p->group = nil;
52474a4d8c2SCharles.Forsyth
52574a4d8c2SCharles.Forsyth if(g->head == nil){
52674a4d8c2SCharles.Forsyth /* move up, giving subgroups of groups with no Progs to their parents */
52774a4d8c2SCharles.Forsyth do{
52874a4d8c2SCharles.Forsyth if((pg = g->parent) != nil){
52974a4d8c2SCharles.Forsyth pg = g->parent;
53074a4d8c2SCharles.Forsyth for(l = &pg->child; *l != nil && *l != g; l = &(*l)->sib)
53174a4d8c2SCharles.Forsyth ;
53274a4d8c2SCharles.Forsyth *l = g->sib;
53374a4d8c2SCharles.Forsyth }
53474a4d8c2SCharles.Forsyth /* put subgroups in new parent group */
53574a4d8c2SCharles.Forsyth while((cg = g->child) != nil){
53674a4d8c2SCharles.Forsyth g->child = cg->sib;
53774a4d8c2SCharles.Forsyth cg->parent = pg;
53874a4d8c2SCharles.Forsyth if(pg != nil){
53974a4d8c2SCharles.Forsyth cg->sib = pg->child;
54074a4d8c2SCharles.Forsyth pg->child = cg;
54174a4d8c2SCharles.Forsyth }
54274a4d8c2SCharles.Forsyth }
54374a4d8c2SCharles.Forsyth free(g);
54474a4d8c2SCharles.Forsyth }while((g = pg) != nil && g->head == nil);
54574a4d8c2SCharles.Forsyth }
54674a4d8c2SCharles.Forsyth return g;
54774a4d8c2SCharles.Forsyth }
54874a4d8c2SCharles.Forsyth
54974a4d8c2SCharles.Forsyth void
printgrp(Prog * p,char * v)55074a4d8c2SCharles.Forsyth printgrp(Prog *p, char *v)
55174a4d8c2SCharles.Forsyth {
55274a4d8c2SCharles.Forsyth Progs *g;
55374a4d8c2SCharles.Forsyth Prog *q;
55474a4d8c2SCharles.Forsyth
55574a4d8c2SCharles.Forsyth g = p->group;
55674a4d8c2SCharles.Forsyth print("%s pid %d grp %d pgrp %d: [pid", v, p->pid, g->id, g->parent!=nil?g->parent->id:0);
55774a4d8c2SCharles.Forsyth for(q = g->head; q != nil; q = q->grpnext)
55874a4d8c2SCharles.Forsyth print(" %d", q->pid);
55974a4d8c2SCharles.Forsyth print(" subgrp");
56074a4d8c2SCharles.Forsyth for(g = g->child; g != nil; g = g->sib)
56174a4d8c2SCharles.Forsyth print(" %d", g->id);
56274a4d8c2SCharles.Forsyth print("]\n");
56374a4d8c2SCharles.Forsyth }
56474a4d8c2SCharles.Forsyth
56574a4d8c2SCharles.Forsyth int
killgrp(Prog * p,char * msg)56674a4d8c2SCharles.Forsyth killgrp(Prog *p, char *msg)
56774a4d8c2SCharles.Forsyth {
56874a4d8c2SCharles.Forsyth int i, npid, *pids;
56974a4d8c2SCharles.Forsyth Prog *f;
57074a4d8c2SCharles.Forsyth Progs *g;
57174a4d8c2SCharles.Forsyth
57274a4d8c2SCharles.Forsyth /* interpreter has been acquired */
57374a4d8c2SCharles.Forsyth g = p->group;
57474a4d8c2SCharles.Forsyth if(g == nil || g->head == nil)
57574a4d8c2SCharles.Forsyth return 0;
576d3ba796fSCharles.Forsyth while(g->flags & Pkilled){
577d3ba796fSCharles.Forsyth release();
578d3ba796fSCharles.Forsyth acquire();
579d3ba796fSCharles.Forsyth }
58074a4d8c2SCharles.Forsyth npid = 0;
58174a4d8c2SCharles.Forsyth for(f = g->head; f != nil; f = f->grpnext)
58274a4d8c2SCharles.Forsyth if(f->group != g)
58374a4d8c2SCharles.Forsyth panic("killgrp");
58474a4d8c2SCharles.Forsyth else
58574a4d8c2SCharles.Forsyth npid++;
586d3ba796fSCharles.Forsyth /* use pids not Prog* because state can change during killprog (eg, in delprog) */
58774a4d8c2SCharles.Forsyth pids = malloc(npid*sizeof(int));
58874a4d8c2SCharles.Forsyth if(pids == nil)
58974a4d8c2SCharles.Forsyth error(Enomem);
59074a4d8c2SCharles.Forsyth npid = 0;
59174a4d8c2SCharles.Forsyth for(f = g->head; f != nil; f = f->grpnext)
59274a4d8c2SCharles.Forsyth pids[npid++] = f->pid;
593d3ba796fSCharles.Forsyth g->flags |= Pkilled;
59474a4d8c2SCharles.Forsyth if(waserror()) {
595d3ba796fSCharles.Forsyth g->flags &= ~Pkilled;
59674a4d8c2SCharles.Forsyth free(pids);
59774a4d8c2SCharles.Forsyth nexterror();
59874a4d8c2SCharles.Forsyth }
59974a4d8c2SCharles.Forsyth for(i = 0; i < npid; i++) {
60074a4d8c2SCharles.Forsyth f = progpid(pids[i]);
60174a4d8c2SCharles.Forsyth if(f != nil && f != currun())
60274a4d8c2SCharles.Forsyth killprog(f, msg);
60374a4d8c2SCharles.Forsyth }
60474a4d8c2SCharles.Forsyth poperror();
605d3ba796fSCharles.Forsyth g->flags &= ~Pkilled;
60674a4d8c2SCharles.Forsyth free(pids);
60774a4d8c2SCharles.Forsyth return 1;
60874a4d8c2SCharles.Forsyth }
60974a4d8c2SCharles.Forsyth
61074a4d8c2SCharles.Forsyth char changup[] = "channel hangup";
61174a4d8c2SCharles.Forsyth
61274a4d8c2SCharles.Forsyth void
killcomm(Progq ** q)61374a4d8c2SCharles.Forsyth killcomm(Progq **q)
61474a4d8c2SCharles.Forsyth {
61574a4d8c2SCharles.Forsyth Prog *p;
61674a4d8c2SCharles.Forsyth Progq *f;
61774a4d8c2SCharles.Forsyth
61874a4d8c2SCharles.Forsyth for (f = *q; f != nil; f = *q) {
61974a4d8c2SCharles.Forsyth *q = f->next;
62074a4d8c2SCharles.Forsyth p = f->prog;
62174a4d8c2SCharles.Forsyth free(f);
62274a4d8c2SCharles.Forsyth if(p == nil)
62374a4d8c2SCharles.Forsyth return;
62474a4d8c2SCharles.Forsyth p->ptr = nil;
62574a4d8c2SCharles.Forsyth switch(p->state) {
62674a4d8c2SCharles.Forsyth case Prelease:
62774a4d8c2SCharles.Forsyth swiprog(p);
62874a4d8c2SCharles.Forsyth break;
62974a4d8c2SCharles.Forsyth case Psend:
63074a4d8c2SCharles.Forsyth case Precv:
63174a4d8c2SCharles.Forsyth p->kill = changup;
63274a4d8c2SCharles.Forsyth addrun(p);
63374a4d8c2SCharles.Forsyth break;
63474a4d8c2SCharles.Forsyth case Palt:
63574a4d8c2SCharles.Forsyth altgone(p);
63674a4d8c2SCharles.Forsyth break;
63774a4d8c2SCharles.Forsyth }
63874a4d8c2SCharles.Forsyth }
63974a4d8c2SCharles.Forsyth }
64074a4d8c2SCharles.Forsyth
64174a4d8c2SCharles.Forsyth void
addprog(Proc * p)64274a4d8c2SCharles.Forsyth addprog(Proc *p)
64374a4d8c2SCharles.Forsyth {
64474a4d8c2SCharles.Forsyth Prog *n;
64574a4d8c2SCharles.Forsyth
64674a4d8c2SCharles.Forsyth if((n = p->prog) == nil) {
64774a4d8c2SCharles.Forsyth n = malloc(sizeof(Prog));
64874a4d8c2SCharles.Forsyth if(n == nil)
64974a4d8c2SCharles.Forsyth panic("no memory");
65074a4d8c2SCharles.Forsyth p->prog = n;
65174a4d8c2SCharles.Forsyth } else
65274a4d8c2SCharles.Forsyth memset(n, 0, sizeof(Prog));
65374a4d8c2SCharles.Forsyth n->osenv = p->env;
65474a4d8c2SCharles.Forsyth }
65574a4d8c2SCharles.Forsyth
65674a4d8c2SCharles.Forsyth static void
cwakeme(Prog * p)65774a4d8c2SCharles.Forsyth cwakeme(Prog *p)
65874a4d8c2SCharles.Forsyth {
65974a4d8c2SCharles.Forsyth Osenv *o;
66074a4d8c2SCharles.Forsyth
66174a4d8c2SCharles.Forsyth p->addrun = nil;
66274a4d8c2SCharles.Forsyth o = p->osenv;
66374a4d8c2SCharles.Forsyth wakeup(o->rend);
66474a4d8c2SCharles.Forsyth }
66574a4d8c2SCharles.Forsyth
66674a4d8c2SCharles.Forsyth static int
cdone(void * vp)66774a4d8c2SCharles.Forsyth cdone(void *vp)
66874a4d8c2SCharles.Forsyth {
66974a4d8c2SCharles.Forsyth Prog *p = vp;
67074a4d8c2SCharles.Forsyth
67174a4d8c2SCharles.Forsyth return p->addrun == nil || p->kill != nil;
67274a4d8c2SCharles.Forsyth }
67374a4d8c2SCharles.Forsyth
67474a4d8c2SCharles.Forsyth void
cblock(Prog * p)67574a4d8c2SCharles.Forsyth cblock(Prog *p)
67674a4d8c2SCharles.Forsyth {
67774a4d8c2SCharles.Forsyth Osenv *o;
67874a4d8c2SCharles.Forsyth
67974a4d8c2SCharles.Forsyth p->addrun = cwakeme;
68074a4d8c2SCharles.Forsyth o = p->osenv;
68174a4d8c2SCharles.Forsyth o->rend = &up->sleep;
68274a4d8c2SCharles.Forsyth release();
68374a4d8c2SCharles.Forsyth
68474a4d8c2SCharles.Forsyth /*
68574a4d8c2SCharles.Forsyth * To allow cdone(p) safely after release,
68674a4d8c2SCharles.Forsyth * p must be currun before the release.
68774a4d8c2SCharles.Forsyth * Exits in the error case with the vm acquired.
68874a4d8c2SCharles.Forsyth */
68974a4d8c2SCharles.Forsyth if(waserror()) {
69074a4d8c2SCharles.Forsyth acquire();
69174a4d8c2SCharles.Forsyth p->addrun = nil;
69274a4d8c2SCharles.Forsyth nexterror();
69374a4d8c2SCharles.Forsyth }
69474a4d8c2SCharles.Forsyth sleep(o->rend, cdone, p);
69574a4d8c2SCharles.Forsyth if (p->kill != nil)
69674a4d8c2SCharles.Forsyth error(Eintr);
69774a4d8c2SCharles.Forsyth poperror();
69874a4d8c2SCharles.Forsyth acquire();
69974a4d8c2SCharles.Forsyth }
70074a4d8c2SCharles.Forsyth
70174a4d8c2SCharles.Forsyth void
addrun(Prog * p)70274a4d8c2SCharles.Forsyth addrun(Prog *p)
70374a4d8c2SCharles.Forsyth {
70474a4d8c2SCharles.Forsyth if(p->addrun != 0) {
70574a4d8c2SCharles.Forsyth p->addrun(p);
70674a4d8c2SCharles.Forsyth return;
70774a4d8c2SCharles.Forsyth }
70874a4d8c2SCharles.Forsyth if(p->state == Pready && p != (Prog *)up->prog)
70974a4d8c2SCharles.Forsyth panic("addrun of ready prog %8.8p by %8.8lux\n", p, getcallerpc(&p));
71074a4d8c2SCharles.Forsyth p->state = Pready;
71174a4d8c2SCharles.Forsyth p->link = nil;
71274a4d8c2SCharles.Forsyth if(isched.runhd == nil)
71374a4d8c2SCharles.Forsyth isched.runhd = p;
71474a4d8c2SCharles.Forsyth else
71574a4d8c2SCharles.Forsyth isched.runtl->link = p;
71674a4d8c2SCharles.Forsyth
71774a4d8c2SCharles.Forsyth isched.runtl = p;
71874a4d8c2SCharles.Forsyth }
71974a4d8c2SCharles.Forsyth
72074a4d8c2SCharles.Forsyth Prog*
delrun(int state)72174a4d8c2SCharles.Forsyth delrun(int state)
72274a4d8c2SCharles.Forsyth {
72374a4d8c2SCharles.Forsyth Prog *p;
72474a4d8c2SCharles.Forsyth
72574a4d8c2SCharles.Forsyth p = isched.runhd;
72674a4d8c2SCharles.Forsyth p->state = state;
72774a4d8c2SCharles.Forsyth isched.runhd = p->link;
72874a4d8c2SCharles.Forsyth if(p->link == nil)
72974a4d8c2SCharles.Forsyth isched.runtl = nil;
73074a4d8c2SCharles.Forsyth
73174a4d8c2SCharles.Forsyth return p;
73274a4d8c2SCharles.Forsyth }
73374a4d8c2SCharles.Forsyth
73474a4d8c2SCharles.Forsyth void
delrunq(Prog * p)73574a4d8c2SCharles.Forsyth delrunq(Prog *p)
73674a4d8c2SCharles.Forsyth {
73774a4d8c2SCharles.Forsyth Prog *prev, *f;
73874a4d8c2SCharles.Forsyth
73974a4d8c2SCharles.Forsyth prev = nil;
74074a4d8c2SCharles.Forsyth for(f = isched.runhd; f; f = f->link) {
74174a4d8c2SCharles.Forsyth if(f == p)
74274a4d8c2SCharles.Forsyth break;
74374a4d8c2SCharles.Forsyth prev = f;
74474a4d8c2SCharles.Forsyth }
74574a4d8c2SCharles.Forsyth if(f == nil)
74674a4d8c2SCharles.Forsyth return;
74774a4d8c2SCharles.Forsyth if(prev == nil)
74874a4d8c2SCharles.Forsyth isched.runhd = p->link;
74974a4d8c2SCharles.Forsyth else
75074a4d8c2SCharles.Forsyth prev->link = p->link;
75174a4d8c2SCharles.Forsyth if(p == isched.runtl)
75274a4d8c2SCharles.Forsyth isched.runtl = prev;
75374a4d8c2SCharles.Forsyth }
75474a4d8c2SCharles.Forsyth
75574a4d8c2SCharles.Forsyth Prog*
delruntail(int state)75674a4d8c2SCharles.Forsyth delruntail(int state)
75774a4d8c2SCharles.Forsyth {
75874a4d8c2SCharles.Forsyth Prog *p;
75974a4d8c2SCharles.Forsyth
76074a4d8c2SCharles.Forsyth p = isched.runtl;
76174a4d8c2SCharles.Forsyth delrunq(isched.runtl);
76274a4d8c2SCharles.Forsyth p->state = state;
76374a4d8c2SCharles.Forsyth return p;
76474a4d8c2SCharles.Forsyth }
76574a4d8c2SCharles.Forsyth
76674a4d8c2SCharles.Forsyth Prog*
currun(void)76774a4d8c2SCharles.Forsyth currun(void)
76874a4d8c2SCharles.Forsyth {
76974a4d8c2SCharles.Forsyth return isched.runhd;
77074a4d8c2SCharles.Forsyth }
77174a4d8c2SCharles.Forsyth
77274a4d8c2SCharles.Forsyth Prog*
schedmod(Module * m)77374a4d8c2SCharles.Forsyth schedmod(Module *m)
77474a4d8c2SCharles.Forsyth {
77574a4d8c2SCharles.Forsyth Heap *h;
77674a4d8c2SCharles.Forsyth Type *t;
77774a4d8c2SCharles.Forsyth Prog *p;
77874a4d8c2SCharles.Forsyth Modlink *ml;
77974a4d8c2SCharles.Forsyth Frame f, *fp;
78074a4d8c2SCharles.Forsyth
78174a4d8c2SCharles.Forsyth ml = mklinkmod(m, 0);
78274a4d8c2SCharles.Forsyth
78374a4d8c2SCharles.Forsyth if(m->origmp != H && m->ntype > 0) {
78474a4d8c2SCharles.Forsyth t = m->type[0];
78574a4d8c2SCharles.Forsyth h = nheap(t->size);
78674a4d8c2SCharles.Forsyth h->t = t;
78774a4d8c2SCharles.Forsyth t->ref++;
78874a4d8c2SCharles.Forsyth ml->MP = H2D(uchar*, h);
78974a4d8c2SCharles.Forsyth newmp(ml->MP, m->origmp, t);
79074a4d8c2SCharles.Forsyth }
79174a4d8c2SCharles.Forsyth
79274a4d8c2SCharles.Forsyth p = newprog(nil, ml);
79374a4d8c2SCharles.Forsyth h = D2H(ml);
79474a4d8c2SCharles.Forsyth h->ref--;
79574a4d8c2SCharles.Forsyth p->R.PC = m->entry;
79674a4d8c2SCharles.Forsyth fp = &f;
79774a4d8c2SCharles.Forsyth R.s = &fp;
79874a4d8c2SCharles.Forsyth f.t = m->entryt;
79974a4d8c2SCharles.Forsyth newstack(p);
80074a4d8c2SCharles.Forsyth initmem(m->entryt, p->R.FP);
80174a4d8c2SCharles.Forsyth
80274a4d8c2SCharles.Forsyth return p;
80374a4d8c2SCharles.Forsyth }
80474a4d8c2SCharles.Forsyth
80574a4d8c2SCharles.Forsyth void
acquire(void)80674a4d8c2SCharles.Forsyth acquire(void)
80774a4d8c2SCharles.Forsyth {
80874a4d8c2SCharles.Forsyth int empty;
80974a4d8c2SCharles.Forsyth Prog *p;
81074a4d8c2SCharles.Forsyth
81174a4d8c2SCharles.Forsyth lock(&isched.l);
81274a4d8c2SCharles.Forsyth if(isched.idle) {
81374a4d8c2SCharles.Forsyth isched.idle = 0;
81474a4d8c2SCharles.Forsyth unlock(&isched.l);
81574a4d8c2SCharles.Forsyth }
81674a4d8c2SCharles.Forsyth else {
81774a4d8c2SCharles.Forsyth up->qnext = nil;
81874a4d8c2SCharles.Forsyth if(isched.vmq != nil){
81974a4d8c2SCharles.Forsyth empty = 0;
82074a4d8c2SCharles.Forsyth isched.vmqt->qnext = up;
82174a4d8c2SCharles.Forsyth }else{
82274a4d8c2SCharles.Forsyth isched.vmq = up;
82374a4d8c2SCharles.Forsyth empty = 1;
82474a4d8c2SCharles.Forsyth }
82574a4d8c2SCharles.Forsyth isched.vmqt = up;
82674a4d8c2SCharles.Forsyth
82774a4d8c2SCharles.Forsyth up->state = Queueing;
82874a4d8c2SCharles.Forsyth up->pc = getcallerpc(&empty);
82974a4d8c2SCharles.Forsyth unlock(&isched.l);
83074a4d8c2SCharles.Forsyth if(empty)
83174a4d8c2SCharles.Forsyth wakeup(&isched.irend);
83274a4d8c2SCharles.Forsyth sched();
83374a4d8c2SCharles.Forsyth }
83474a4d8c2SCharles.Forsyth
83574a4d8c2SCharles.Forsyth if(up->type == Interp) {
83674a4d8c2SCharles.Forsyth p = up->iprog;
83774a4d8c2SCharles.Forsyth up->iprog = nil;
83874a4d8c2SCharles.Forsyth irestore(p);
83974a4d8c2SCharles.Forsyth }
84074a4d8c2SCharles.Forsyth else
84174a4d8c2SCharles.Forsyth p = up->prog;
84274a4d8c2SCharles.Forsyth
84374a4d8c2SCharles.Forsyth p->state = Pready;
84474a4d8c2SCharles.Forsyth p->link = isched.runhd;
84574a4d8c2SCharles.Forsyth isched.runhd = p;
84674a4d8c2SCharles.Forsyth if(p->link == nil)
84774a4d8c2SCharles.Forsyth isched.runtl = p;
84874a4d8c2SCharles.Forsyth }
84974a4d8c2SCharles.Forsyth
85074a4d8c2SCharles.Forsyth void
release(void)85174a4d8c2SCharles.Forsyth release(void)
85274a4d8c2SCharles.Forsyth {
85374a4d8c2SCharles.Forsyth Proc *p, **pq;
85474a4d8c2SCharles.Forsyth int f;
85574a4d8c2SCharles.Forsyth
85674a4d8c2SCharles.Forsyth if(up->type == Interp){
85774a4d8c2SCharles.Forsyth if(up->iprog != nil)
85874a4d8c2SCharles.Forsyth panic("Double release (Interp)?");
85974a4d8c2SCharles.Forsyth up->iprog = isave();
86074a4d8c2SCharles.Forsyth }else{
86174a4d8c2SCharles.Forsyth if(((Prog *)up->prog)->state != Pready) panic("double release (GC)?");
86274a4d8c2SCharles.Forsyth delrun(Prelease);
86374a4d8c2SCharles.Forsyth }
86474a4d8c2SCharles.Forsyth
86574a4d8c2SCharles.Forsyth lock(&isched.l);
86674a4d8c2SCharles.Forsyth if(*(pq = &isched.vmq) == nil && *(pq = &isched.idlevmq) == nil) {
86774a4d8c2SCharles.Forsyth isched.idle = 1;
86874a4d8c2SCharles.Forsyth f = isched.creating;
86974a4d8c2SCharles.Forsyth isched.creating = 1;
87074a4d8c2SCharles.Forsyth unlock(&isched.l);
87174a4d8c2SCharles.Forsyth if(f == 0)
87274a4d8c2SCharles.Forsyth kproc("dis", vmachine, nil, 0);
87374a4d8c2SCharles.Forsyth return;
87474a4d8c2SCharles.Forsyth }
87574a4d8c2SCharles.Forsyth p = *pq;
87674a4d8c2SCharles.Forsyth *pq = p->qnext;
87774a4d8c2SCharles.Forsyth unlock(&isched.l);
87874a4d8c2SCharles.Forsyth
87974a4d8c2SCharles.Forsyth ready(p);
88074a4d8c2SCharles.Forsyth }
88174a4d8c2SCharles.Forsyth
88274a4d8c2SCharles.Forsyth void
iyield(void)88374a4d8c2SCharles.Forsyth iyield(void)
88474a4d8c2SCharles.Forsyth {
88574a4d8c2SCharles.Forsyth Proc *p;
88674a4d8c2SCharles.Forsyth
88774a4d8c2SCharles.Forsyth lock(&isched.l);
88874a4d8c2SCharles.Forsyth p = isched.vmq;
88974a4d8c2SCharles.Forsyth if(p == nil) {
89074a4d8c2SCharles.Forsyth unlock(&isched.l);
89174a4d8c2SCharles.Forsyth return;
89274a4d8c2SCharles.Forsyth }
89374a4d8c2SCharles.Forsyth isched.nyield++;
89474a4d8c2SCharles.Forsyth isched.vmq = p->qnext;
89574a4d8c2SCharles.Forsyth
89674a4d8c2SCharles.Forsyth if(up->iprog != nil)
89774a4d8c2SCharles.Forsyth panic("iyield but iprog, type %d", up->type);
89874a4d8c2SCharles.Forsyth if(up->type != Interp){
89974a4d8c2SCharles.Forsyth static int once;
90074a4d8c2SCharles.Forsyth if(!once++)
90174a4d8c2SCharles.Forsyth print("tell charles: #%p->type==%d\n", up, up->type);
90274a4d8c2SCharles.Forsyth }
90374a4d8c2SCharles.Forsyth up->qnext = isched.idlevmq;
90474a4d8c2SCharles.Forsyth isched.idlevmq = up;
90574a4d8c2SCharles.Forsyth
90674a4d8c2SCharles.Forsyth up->state = Queueing;
90774a4d8c2SCharles.Forsyth up->pc = getcallerpc(&p);
90874a4d8c2SCharles.Forsyth unlock(&isched.l);
90974a4d8c2SCharles.Forsyth ready(p);
91074a4d8c2SCharles.Forsyth sched();
91174a4d8c2SCharles.Forsyth }
91274a4d8c2SCharles.Forsyth
91374a4d8c2SCharles.Forsyth void
startup(void)91474a4d8c2SCharles.Forsyth startup(void)
91574a4d8c2SCharles.Forsyth {
91674a4d8c2SCharles.Forsyth int x;
91774a4d8c2SCharles.Forsyth
91874a4d8c2SCharles.Forsyth up->type = Interp;
91974a4d8c2SCharles.Forsyth up->iprog = nil;
92074a4d8c2SCharles.Forsyth
92174a4d8c2SCharles.Forsyth lock(&isched.l);
92274a4d8c2SCharles.Forsyth isched.creating = 0;
92374a4d8c2SCharles.Forsyth if(isched.idle) {
92474a4d8c2SCharles.Forsyth isched.idle = 0;
92574a4d8c2SCharles.Forsyth unlock(&isched.l);
92674a4d8c2SCharles.Forsyth return;
92774a4d8c2SCharles.Forsyth }
92874a4d8c2SCharles.Forsyth up->qnext = isched.idlevmq;
92974a4d8c2SCharles.Forsyth isched.idlevmq = up;
93074a4d8c2SCharles.Forsyth up->state = Queueing;
93174a4d8c2SCharles.Forsyth up->pc = getcallerpc(&x);
93274a4d8c2SCharles.Forsyth unlock(&isched.l);
93374a4d8c2SCharles.Forsyth sched();
93474a4d8c2SCharles.Forsyth }
93574a4d8c2SCharles.Forsyth
93674a4d8c2SCharles.Forsyth void
progexit(void)93774a4d8c2SCharles.Forsyth progexit(void)
93874a4d8c2SCharles.Forsyth {
93974a4d8c2SCharles.Forsyth Prog *r;
94074a4d8c2SCharles.Forsyth Module *m;
94174a4d8c2SCharles.Forsyth int broken;
94274a4d8c2SCharles.Forsyth char *estr, msg[ERRMAX+2*KNAMELEN];
94374a4d8c2SCharles.Forsyth
94474a4d8c2SCharles.Forsyth estr = up->env->errstr;
94574a4d8c2SCharles.Forsyth broken = 0;
94674a4d8c2SCharles.Forsyth if(estr[0] != '\0' && strcmp(estr, Eintr) != 0 && strncmp(estr, "fail:", 5) != 0)
94774a4d8c2SCharles.Forsyth broken = 1;
94874a4d8c2SCharles.Forsyth
94974a4d8c2SCharles.Forsyth r = up->iprog;
95074a4d8c2SCharles.Forsyth if(r != nil)
95174a4d8c2SCharles.Forsyth acquire();
95274a4d8c2SCharles.Forsyth else
95374a4d8c2SCharles.Forsyth r = currun();
95474a4d8c2SCharles.Forsyth
95574a4d8c2SCharles.Forsyth if(*estr == '\0' && r->flags & Pkilled)
95674a4d8c2SCharles.Forsyth estr = "killed";
95774a4d8c2SCharles.Forsyth
95874a4d8c2SCharles.Forsyth m = R.M->m;
95974a4d8c2SCharles.Forsyth if(broken)
96074a4d8c2SCharles.Forsyth print("[%s] Broken: \"%s\"\n", m->name, estr);
96174a4d8c2SCharles.Forsyth
96274a4d8c2SCharles.Forsyth snprint(msg, sizeof(msg), "%d \"%s\":%s", r->pid, m->name, estr);
96374a4d8c2SCharles.Forsyth
96474a4d8c2SCharles.Forsyth if(up->env->debug != nil) {
96574a4d8c2SCharles.Forsyth dbgexit(r, broken, estr);
96674a4d8c2SCharles.Forsyth broken = 1;
96774a4d8c2SCharles.Forsyth /* must force it to break if in debug */
96874a4d8c2SCharles.Forsyth }else if(broken && (!keepbroken || strncmp(estr, "out of memory", 13)==0 || memusehigh()))
96974a4d8c2SCharles.Forsyth broken = 0; /* don't want them or short of memory */
97074a4d8c2SCharles.Forsyth
97174a4d8c2SCharles.Forsyth if(broken){
97274a4d8c2SCharles.Forsyth tellsomeone(r, msg);
97374a4d8c2SCharles.Forsyth r = isave();
97474a4d8c2SCharles.Forsyth r->state = Pbroken;
97574a4d8c2SCharles.Forsyth return;
97674a4d8c2SCharles.Forsyth }
97774a4d8c2SCharles.Forsyth
97874a4d8c2SCharles.Forsyth gclock();
97974a4d8c2SCharles.Forsyth destroystack(&R);
98074a4d8c2SCharles.Forsyth delprog(r, msg);
98174a4d8c2SCharles.Forsyth gcunlock();
98274a4d8c2SCharles.Forsyth }
98374a4d8c2SCharles.Forsyth
98474a4d8c2SCharles.Forsyth void
disfault(void * reg,char * msg)98574a4d8c2SCharles.Forsyth disfault(void *reg, char *msg)
98674a4d8c2SCharles.Forsyth {
98774a4d8c2SCharles.Forsyth Prog *p;
98874a4d8c2SCharles.Forsyth
98974a4d8c2SCharles.Forsyth USED(reg);
99074a4d8c2SCharles.Forsyth
99174a4d8c2SCharles.Forsyth if(strncmp(msg, Eintr, 6) == 0 || up == nil) {
99274a4d8c2SCharles.Forsyth print("EMU: faults: %s\n", msg);
99374a4d8c2SCharles.Forsyth panic("disfault");
99474a4d8c2SCharles.Forsyth }
99574a4d8c2SCharles.Forsyth if(up->type != Interp) {
99674a4d8c2SCharles.Forsyth print("SYS: process %s faults: %s\n", up->text, msg);
99774a4d8c2SCharles.Forsyth panic("disfault");
99874a4d8c2SCharles.Forsyth }
99974a4d8c2SCharles.Forsyth
100074a4d8c2SCharles.Forsyth if(up->iprog != nil)
100174a4d8c2SCharles.Forsyth acquire();
100274a4d8c2SCharles.Forsyth
100374a4d8c2SCharles.Forsyth p = currun();
100474a4d8c2SCharles.Forsyth if(p == nil)
100574a4d8c2SCharles.Forsyth panic("Interp faults with no dis prog");
100674a4d8c2SCharles.Forsyth
100774a4d8c2SCharles.Forsyth /* cause an exception in the dis prog. */
100874a4d8c2SCharles.Forsyth error(msg);
100974a4d8c2SCharles.Forsyth }
101074a4d8c2SCharles.Forsyth
101174a4d8c2SCharles.Forsyth void
vmachine(void *)101274a4d8c2SCharles.Forsyth vmachine(void*)
101374a4d8c2SCharles.Forsyth {
101474a4d8c2SCharles.Forsyth Prog *r;
101574a4d8c2SCharles.Forsyth Osenv *o;
101674a4d8c2SCharles.Forsyth int cycles;
101774a4d8c2SCharles.Forsyth
101874a4d8c2SCharles.Forsyth startup();
101974a4d8c2SCharles.Forsyth
102074a4d8c2SCharles.Forsyth while(waserror()) {
102174a4d8c2SCharles.Forsyth if(up->type != Interp)
102274a4d8c2SCharles.Forsyth panic("vmachine: non-interp kproc");
102374a4d8c2SCharles.Forsyth if(up->iprog != nil)
102474a4d8c2SCharles.Forsyth acquire();
102574a4d8c2SCharles.Forsyth if(handler(up->env->errstr) == 0) {
102674a4d8c2SCharles.Forsyth propex(currun(), up->env->errstr);
102774a4d8c2SCharles.Forsyth progexit();
102874a4d8c2SCharles.Forsyth }
102974a4d8c2SCharles.Forsyth up->env = &up->defenv;
103074a4d8c2SCharles.Forsyth }
103174a4d8c2SCharles.Forsyth
103274a4d8c2SCharles.Forsyth cycles = 0;
103374a4d8c2SCharles.Forsyth for(;;) {
103474a4d8c2SCharles.Forsyth if(tready(nil) == 0) {
103574a4d8c2SCharles.Forsyth execatidle();
103674a4d8c2SCharles.Forsyth sleep(&isched.irend, tready, 0);
103774a4d8c2SCharles.Forsyth }
103874a4d8c2SCharles.Forsyth
103974a4d8c2SCharles.Forsyth if(isched.vmq != nil && (isched.runhd == nil || ++cycles > 2)){
104074a4d8c2SCharles.Forsyth iyield();
104174a4d8c2SCharles.Forsyth cycles = 0;
104274a4d8c2SCharles.Forsyth }
104374a4d8c2SCharles.Forsyth
104474a4d8c2SCharles.Forsyth r = isched.runhd;
104574a4d8c2SCharles.Forsyth if(r != nil) {
104674a4d8c2SCharles.Forsyth o = r->osenv;
104774a4d8c2SCharles.Forsyth up->env = o;
104874a4d8c2SCharles.Forsyth
104974a4d8c2SCharles.Forsyth FPrestore(&o->fpu);
105074a4d8c2SCharles.Forsyth r->xec(r);
105174a4d8c2SCharles.Forsyth FPsave(&o->fpu);
105274a4d8c2SCharles.Forsyth
105374a4d8c2SCharles.Forsyth if(isched.runhd != nil)
105474a4d8c2SCharles.Forsyth if(r == isched.runhd)
105574a4d8c2SCharles.Forsyth if(isched.runhd != isched.runtl) {
105674a4d8c2SCharles.Forsyth isched.runhd = r->link;
105774a4d8c2SCharles.Forsyth r->link = nil;
105874a4d8c2SCharles.Forsyth isched.runtl->link = r;
105974a4d8c2SCharles.Forsyth isched.runtl = r;
106074a4d8c2SCharles.Forsyth }
106174a4d8c2SCharles.Forsyth up->env = &up->defenv;
106274a4d8c2SCharles.Forsyth if(isched.runhd != nil)
106374a4d8c2SCharles.Forsyth if (up->iprog == nil) {
106474a4d8c2SCharles.Forsyth up->type = BusyGC;
106574a4d8c2SCharles.Forsyth pushrun(up->prog);
106674a4d8c2SCharles.Forsyth rungc(isched.head);
106774a4d8c2SCharles.Forsyth up->type = Interp;
106874a4d8c2SCharles.Forsyth delrunq(up->prog);
106974a4d8c2SCharles.Forsyth } else
107074a4d8c2SCharles.Forsyth print("up->iprog not nil (%lux)\n", up->iprog);
107174a4d8c2SCharles.Forsyth }
107274a4d8c2SCharles.Forsyth }
107374a4d8c2SCharles.Forsyth }
107474a4d8c2SCharles.Forsyth
107574a4d8c2SCharles.Forsyth void
disinit(void * a)107674a4d8c2SCharles.Forsyth disinit(void *a)
107774a4d8c2SCharles.Forsyth {
107874a4d8c2SCharles.Forsyth Prog *p;
107974a4d8c2SCharles.Forsyth Osenv *o;
108074a4d8c2SCharles.Forsyth Module *root;
108174a4d8c2SCharles.Forsyth char *initmod = a;
108274a4d8c2SCharles.Forsyth
108374a4d8c2SCharles.Forsyth if(waserror())
108474a4d8c2SCharles.Forsyth panic("disinit error: %r");
108574a4d8c2SCharles.Forsyth
108674a4d8c2SCharles.Forsyth print("Initial Dis: \"%s\"\n", initmod);
108774a4d8c2SCharles.Forsyth
108874a4d8c2SCharles.Forsyth fmtinstall('D', Dconv);
108974a4d8c2SCharles.Forsyth
109074a4d8c2SCharles.Forsyth addclock0link(accountant, MS2HZ);
109174a4d8c2SCharles.Forsyth
109274a4d8c2SCharles.Forsyth FPinit();
109374a4d8c2SCharles.Forsyth FPsave(&up->env->fpu);
109474a4d8c2SCharles.Forsyth
109574a4d8c2SCharles.Forsyth opinit();
109674a4d8c2SCharles.Forsyth modinit();
109774a4d8c2SCharles.Forsyth excinit();
109874a4d8c2SCharles.Forsyth
109974a4d8c2SCharles.Forsyth root = load(initmod);
110074a4d8c2SCharles.Forsyth if(root == 0) {
110174a4d8c2SCharles.Forsyth kgerrstr(up->genbuf, sizeof up->genbuf);
110274a4d8c2SCharles.Forsyth panic("loading \"%s\": %s", initmod, up->genbuf);
110374a4d8c2SCharles.Forsyth }
110474a4d8c2SCharles.Forsyth
110574a4d8c2SCharles.Forsyth p = schedmod(root);
110674a4d8c2SCharles.Forsyth
110774a4d8c2SCharles.Forsyth memmove(p->osenv, up->env, sizeof(Osenv));
110874a4d8c2SCharles.Forsyth o = p->osenv;
110974a4d8c2SCharles.Forsyth incref(o->pgrp);
111074a4d8c2SCharles.Forsyth incref(o->fgrp);
111174a4d8c2SCharles.Forsyth if(o->egrp != nil)
111274a4d8c2SCharles.Forsyth incref(o->egrp);
111374a4d8c2SCharles.Forsyth if(o->sigs != nil)
111474a4d8c2SCharles.Forsyth incref(o->sigs);
111574a4d8c2SCharles.Forsyth o->user = nil;
111674a4d8c2SCharles.Forsyth kstrdup(&o->user, up->env->user);
111774a4d8c2SCharles.Forsyth o->errstr = o->errbuf0;
111874a4d8c2SCharles.Forsyth o->syserrstr = o->errbuf1;
111974a4d8c2SCharles.Forsyth
112074a4d8c2SCharles.Forsyth isched.idle = 1;
112174a4d8c2SCharles.Forsyth
112274a4d8c2SCharles.Forsyth if(kopen("#c/cons", OREAD) != 0)
112374a4d8c2SCharles.Forsyth panic("failed to make fd0 from #c/cons");
112474a4d8c2SCharles.Forsyth kopen("#c/cons", OWRITE);
112574a4d8c2SCharles.Forsyth kopen("#c/cons", OWRITE);
112674a4d8c2SCharles.Forsyth
112774a4d8c2SCharles.Forsyth poperror();
112874a4d8c2SCharles.Forsyth vmachine(nil);
112974a4d8c2SCharles.Forsyth }
113074a4d8c2SCharles.Forsyth
113174a4d8c2SCharles.Forsyth void
pushrun(Prog * p)113274a4d8c2SCharles.Forsyth pushrun(Prog *p)
113374a4d8c2SCharles.Forsyth {
113474a4d8c2SCharles.Forsyth if(p->addrun != nil)
113574a4d8c2SCharles.Forsyth panic("pushrun addrun");
113674a4d8c2SCharles.Forsyth p->state = Pready;
113774a4d8c2SCharles.Forsyth p->link = isched.runhd;
113874a4d8c2SCharles.Forsyth isched.runhd = p;
113974a4d8c2SCharles.Forsyth if(p->link == nil)
114074a4d8c2SCharles.Forsyth isched.runtl = p;
114174a4d8c2SCharles.Forsyth }
1142