xref: /inferno-os/os/port/dis.c (revision 112f90aed6c636816f40afc88ae63af0966c9e3a)
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