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