xref: /plan9-contrib/sys/src/9k/port/pgrp.c (revision 406c76facc4b13aa2a55454bf4091aab9f03da22)
19ef1f84bSDavid du Colombier #include	"u.h"
29ef1f84bSDavid du Colombier #include	"../port/lib.h"
39ef1f84bSDavid du Colombier #include	"mem.h"
49ef1f84bSDavid du Colombier #include	"dat.h"
59ef1f84bSDavid du Colombier #include	"fns.h"
69ef1f84bSDavid du Colombier #include	"../port/error.h"
79ef1f84bSDavid du Colombier 
8*406c76faSDavid du Colombier enum {
9*406c76faSDavid du Colombier 	Whinesecs = 10,		/* frequency of out-of-resources printing */
10*406c76faSDavid du Colombier };
11*406c76faSDavid du Colombier 
129ef1f84bSDavid du Colombier static Ref pgrpid;
139ef1f84bSDavid du Colombier static Ref mountid;
149ef1f84bSDavid du Colombier 
159ef1f84bSDavid du Colombier void
pgrpnote(ulong noteid,char * a,long n,int flag)169ef1f84bSDavid du Colombier pgrpnote(ulong noteid, char *a, long n, int flag)
179ef1f84bSDavid du Colombier {
189ef1f84bSDavid du Colombier 	int i;
199ef1f84bSDavid du Colombier 	Proc *p;
209ef1f84bSDavid du Colombier 	char buf[ERRMAX];
219ef1f84bSDavid du Colombier 
229ef1f84bSDavid du Colombier 	if(n >= ERRMAX-1)
239ef1f84bSDavid du Colombier 		error(Etoobig);
249ef1f84bSDavid du Colombier 
259ef1f84bSDavid du Colombier 	memmove(buf, a, n);
269ef1f84bSDavid du Colombier 	buf[n] = 0;
279ef1f84bSDavid du Colombier 	for(i = 0; (p = psincref(i)) != nil; i++){
289ef1f84bSDavid du Colombier 		if(p == up || p->state == Dead || p->noteid != noteid || p->kp){
299ef1f84bSDavid du Colombier 			psdecref(p);
309ef1f84bSDavid du Colombier 			continue;
319ef1f84bSDavid du Colombier 		}
329ef1f84bSDavid du Colombier 		qlock(&p->debug);
339ef1f84bSDavid du Colombier 		if(p->pid == 0 || p->noteid != noteid){
349ef1f84bSDavid du Colombier 			qunlock(&p->debug);
359ef1f84bSDavid du Colombier 			psdecref(p);
369ef1f84bSDavid du Colombier 			continue;
379ef1f84bSDavid du Colombier 		}
389ef1f84bSDavid du Colombier 		if(!waserror()) {
399ef1f84bSDavid du Colombier 			postnote(p, 0, buf, flag);
409ef1f84bSDavid du Colombier 			poperror();
419ef1f84bSDavid du Colombier 		}
429ef1f84bSDavid du Colombier 		qunlock(&p->debug);
439ef1f84bSDavid du Colombier 		psdecref(p);
449ef1f84bSDavid du Colombier 	}
459ef1f84bSDavid du Colombier }
469ef1f84bSDavid du Colombier 
479ef1f84bSDavid du Colombier Pgrp*
newpgrp(void)489ef1f84bSDavid du Colombier newpgrp(void)
499ef1f84bSDavid du Colombier {
509ef1f84bSDavid du Colombier 	Pgrp *p;
519ef1f84bSDavid du Colombier 
529ef1f84bSDavid du Colombier 	p = smalloc(sizeof(Pgrp));
539ef1f84bSDavid du Colombier 	p->ref = 1;
549ef1f84bSDavid du Colombier 	p->pgrpid = incref(&pgrpid);
559ef1f84bSDavid du Colombier 	return p;
569ef1f84bSDavid du Colombier }
579ef1f84bSDavid du Colombier 
589ef1f84bSDavid du Colombier Rgrp*
newrgrp(void)599ef1f84bSDavid du Colombier newrgrp(void)
609ef1f84bSDavid du Colombier {
619ef1f84bSDavid du Colombier 	Rgrp *r;
629ef1f84bSDavid du Colombier 
639ef1f84bSDavid du Colombier 	r = smalloc(sizeof(Rgrp));
649ef1f84bSDavid du Colombier 	r->ref = 1;
659ef1f84bSDavid du Colombier 	return r;
669ef1f84bSDavid du Colombier }
679ef1f84bSDavid du Colombier 
689ef1f84bSDavid du Colombier void
closergrp(Rgrp * r)699ef1f84bSDavid du Colombier closergrp(Rgrp *r)
709ef1f84bSDavid du Colombier {
719ef1f84bSDavid du Colombier 	if(decref(r) == 0)
729ef1f84bSDavid du Colombier 		free(r);
739ef1f84bSDavid du Colombier }
749ef1f84bSDavid du Colombier 
759ef1f84bSDavid du Colombier void
closepgrp(Pgrp * p)769ef1f84bSDavid du Colombier closepgrp(Pgrp *p)
779ef1f84bSDavid du Colombier {
789ef1f84bSDavid du Colombier 	Mhead **h, **e, *f, *next;
799ef1f84bSDavid du Colombier 
809ef1f84bSDavid du Colombier 	if(decref(p) != 0)
819ef1f84bSDavid du Colombier 		return;
829ef1f84bSDavid du Colombier 
839ef1f84bSDavid du Colombier 	qlock(&p->debug);
849ef1f84bSDavid du Colombier 	wlock(&p->ns);
859ef1f84bSDavid du Colombier 	p->pgrpid = -1;
869ef1f84bSDavid du Colombier 
879ef1f84bSDavid du Colombier 	e = &p->mnthash[MNTHASH];
889ef1f84bSDavid du Colombier 	for(h = p->mnthash; h < e; h++) {
899ef1f84bSDavid du Colombier 		for(f = *h; f; f = next) {
909ef1f84bSDavid du Colombier 			wlock(&f->lock);
919ef1f84bSDavid du Colombier 			cclose(f->from);
929ef1f84bSDavid du Colombier 			mountfree(f->mount);
939ef1f84bSDavid du Colombier 			f->mount = nil;
949ef1f84bSDavid du Colombier 			next = f->hash;
959ef1f84bSDavid du Colombier 			wunlock(&f->lock);
969ef1f84bSDavid du Colombier 			putmhead(f);
979ef1f84bSDavid du Colombier 		}
989ef1f84bSDavid du Colombier 	}
999ef1f84bSDavid du Colombier 	wunlock(&p->ns);
1009ef1f84bSDavid du Colombier 	qunlock(&p->debug);
1019ef1f84bSDavid du Colombier 	free(p);
1029ef1f84bSDavid du Colombier }
1039ef1f84bSDavid du Colombier 
1049ef1f84bSDavid du Colombier void
pgrpinsert(Mount ** order,Mount * mount)1059ef1f84bSDavid du Colombier pgrpinsert(Mount **order, Mount *mount)
1069ef1f84bSDavid du Colombier {
1079ef1f84bSDavid du Colombier 	Mount *f;
1089ef1f84bSDavid du Colombier 
1099ef1f84bSDavid du Colombier 	mount->order = 0;
1109ef1f84bSDavid du Colombier 	if(*order == 0) {
1119ef1f84bSDavid du Colombier 		*order = mount;
1129ef1f84bSDavid du Colombier 		return;
1139ef1f84bSDavid du Colombier 	}
1149ef1f84bSDavid du Colombier 	for(f = *order; f; f = f->order) {
1159ef1f84bSDavid du Colombier 		if(mount->mountid < f->mountid) {
1169ef1f84bSDavid du Colombier 			mount->order = f;
1179ef1f84bSDavid du Colombier 			*order = mount;
1189ef1f84bSDavid du Colombier 			return;
1199ef1f84bSDavid du Colombier 		}
1209ef1f84bSDavid du Colombier 		order = &f->order;
1219ef1f84bSDavid du Colombier 	}
1229ef1f84bSDavid du Colombier 	*order = mount;
1239ef1f84bSDavid du Colombier }
1249ef1f84bSDavid du Colombier 
1259ef1f84bSDavid du Colombier /*
1269ef1f84bSDavid du Colombier  * pgrpcpy MUST preserve the mountid allocation order of the parent group
1279ef1f84bSDavid du Colombier  */
1289ef1f84bSDavid du Colombier void
pgrpcpy(Pgrp * to,Pgrp * from)1299ef1f84bSDavid du Colombier pgrpcpy(Pgrp *to, Pgrp *from)
1309ef1f84bSDavid du Colombier {
1319ef1f84bSDavid du Colombier 	int i;
1329ef1f84bSDavid du Colombier 	Mount *n, *mount, **link, *order;
1339ef1f84bSDavid du Colombier 	Mhead *f, **tom, **l, *mh;
1349ef1f84bSDavid du Colombier 
1359ef1f84bSDavid du Colombier 	wlock(&from->ns);
1369ef1f84bSDavid du Colombier 	order = 0;
1379ef1f84bSDavid du Colombier 	tom = to->mnthash;
1389ef1f84bSDavid du Colombier 	for(i = 0; i < MNTHASH; i++) {
1399ef1f84bSDavid du Colombier 		l = tom++;
1409ef1f84bSDavid du Colombier 		for(f = from->mnthash[i]; f; f = f->hash) {
1419ef1f84bSDavid du Colombier 			rlock(&f->lock);
1429ef1f84bSDavid du Colombier 			mh = newmhead(f->from);
1439ef1f84bSDavid du Colombier 			*l = mh;
1449ef1f84bSDavid du Colombier 			l = &mh->hash;
1459ef1f84bSDavid du Colombier 			link = &mh->mount;
1469ef1f84bSDavid du Colombier 			for(mount = f->mount; mount != nil; mount = mount->next) {
1479ef1f84bSDavid du Colombier 				n = newmount(mh, mount->to, mount->mflag, mount->spec);
1489ef1f84bSDavid du Colombier 				mount->copy = n;
1499ef1f84bSDavid du Colombier 				pgrpinsert(&order, mount);
1509ef1f84bSDavid du Colombier 				*link = n;
1519ef1f84bSDavid du Colombier 				link = &n->next;
1529ef1f84bSDavid du Colombier 			}
1539ef1f84bSDavid du Colombier 			runlock(&f->lock);
1549ef1f84bSDavid du Colombier 		}
1559ef1f84bSDavid du Colombier 	}
1569ef1f84bSDavid du Colombier 	/*
1579ef1f84bSDavid du Colombier 	 * Allocate mount ids in the same sequence as the parent group
1589ef1f84bSDavid du Colombier 	 */
1599ef1f84bSDavid du Colombier 	lock(&mountid);
1609ef1f84bSDavid du Colombier 	for(mount = order; mount != nil; mount = mount->order)
1619ef1f84bSDavid du Colombier 		mount->copy->mountid = mountid.ref++;
1629ef1f84bSDavid du Colombier 	unlock(&mountid);
1639ef1f84bSDavid du Colombier 	wunlock(&from->ns);
1649ef1f84bSDavid du Colombier }
1659ef1f84bSDavid du Colombier 
1669ef1f84bSDavid du Colombier Fgrp*
dupfgrp(Fgrp * f)1679ef1f84bSDavid du Colombier dupfgrp(Fgrp *f)
1689ef1f84bSDavid du Colombier {
1699ef1f84bSDavid du Colombier 	Fgrp *new;
1709ef1f84bSDavid du Colombier 	Chan *c;
1719ef1f84bSDavid du Colombier 	int i;
1729ef1f84bSDavid du Colombier 
1739ef1f84bSDavid du Colombier 	new = smalloc(sizeof(Fgrp));
1749ef1f84bSDavid du Colombier 	if(f == nil){
1759ef1f84bSDavid du Colombier 		new->fd = smalloc(DELTAFD*sizeof(Chan*));
1769ef1f84bSDavid du Colombier 		new->nfd = DELTAFD;
1779ef1f84bSDavid du Colombier 		new->ref = 1;
1789ef1f84bSDavid du Colombier 		return new;
1799ef1f84bSDavid du Colombier 	}
1809ef1f84bSDavid du Colombier 
1819ef1f84bSDavid du Colombier 	lock(f);
1829ef1f84bSDavid du Colombier 	/* Make new fd list shorter if possible, preserving quantization */
1839ef1f84bSDavid du Colombier 	new->nfd = f->maxfd+1;
1849ef1f84bSDavid du Colombier 	i = new->nfd%DELTAFD;
1859ef1f84bSDavid du Colombier 	if(i != 0)
1869ef1f84bSDavid du Colombier 		new->nfd += DELTAFD - i;
1879ef1f84bSDavid du Colombier 	new->fd = malloc(new->nfd*sizeof(Chan*));
1889ef1f84bSDavid du Colombier 	if(new->fd == nil){
1899ef1f84bSDavid du Colombier 		unlock(f);
1909ef1f84bSDavid du Colombier 		free(new);
1919ef1f84bSDavid du Colombier 		error("no memory for fgrp");
1929ef1f84bSDavid du Colombier 	}
1939ef1f84bSDavid du Colombier 	new->ref = 1;
1949ef1f84bSDavid du Colombier 
1959ef1f84bSDavid du Colombier 	new->maxfd = f->maxfd;
1969ef1f84bSDavid du Colombier 	for(i = 0; i <= f->maxfd; i++) {
1979ef1f84bSDavid du Colombier 		if(c = f->fd[i]){
1989ef1f84bSDavid du Colombier 			incref(c);
1999ef1f84bSDavid du Colombier 			new->fd[i] = c;
2009ef1f84bSDavid du Colombier 		}
2019ef1f84bSDavid du Colombier 	}
2029ef1f84bSDavid du Colombier 	unlock(f);
2039ef1f84bSDavid du Colombier 
2049ef1f84bSDavid du Colombier 	return new;
2059ef1f84bSDavid du Colombier }
2069ef1f84bSDavid du Colombier 
2079ef1f84bSDavid du Colombier void
closefgrp(Fgrp * f)2089ef1f84bSDavid du Colombier closefgrp(Fgrp *f)
2099ef1f84bSDavid du Colombier {
2109ef1f84bSDavid du Colombier 	int i;
2119ef1f84bSDavid du Colombier 	Chan *c;
2129ef1f84bSDavid du Colombier 
2139ef1f84bSDavid du Colombier 	if(f == 0)
2149ef1f84bSDavid du Colombier 		return;
2159ef1f84bSDavid du Colombier 
2169ef1f84bSDavid du Colombier 	if(decref(f) != 0)
2179ef1f84bSDavid du Colombier 		return;
2189ef1f84bSDavid du Colombier 
2199ef1f84bSDavid du Colombier 	/*
2209ef1f84bSDavid du Colombier 	 * If we get into trouble, forceclosefgrp
2219ef1f84bSDavid du Colombier 	 * will bail us out.
2229ef1f84bSDavid du Colombier 	 */
2239ef1f84bSDavid du Colombier 	up->closingfgrp = f;
2249ef1f84bSDavid du Colombier 	for(i = 0; i <= f->maxfd; i++){
2259ef1f84bSDavid du Colombier 		if(c = f->fd[i]){
2269ef1f84bSDavid du Colombier 			f->fd[i] = nil;
2279ef1f84bSDavid du Colombier 			cclose(c);
2289ef1f84bSDavid du Colombier 		}
2299ef1f84bSDavid du Colombier 	}
2309ef1f84bSDavid du Colombier 	up->closingfgrp = nil;
2319ef1f84bSDavid du Colombier 
2329ef1f84bSDavid du Colombier 	free(f->fd);
2339ef1f84bSDavid du Colombier 	free(f);
2349ef1f84bSDavid du Colombier }
2359ef1f84bSDavid du Colombier 
2369ef1f84bSDavid du Colombier /*
2379ef1f84bSDavid du Colombier  * Called from sleep because up is in the middle
2389ef1f84bSDavid du Colombier  * of closefgrp and just got a kill ctl message.
2399ef1f84bSDavid du Colombier  * This usually means that up has wedged because
2409ef1f84bSDavid du Colombier  * of some kind of deadly embrace with mntclose
2419ef1f84bSDavid du Colombier  * trying to talk to itself.  To break free, hand the
2429ef1f84bSDavid du Colombier  * unclosed channels to the close queue.  Once they
2439ef1f84bSDavid du Colombier  * are finished, the blocked cclose that we've
2449ef1f84bSDavid du Colombier  * interrupted will finish by itself.
2459ef1f84bSDavid du Colombier  */
2469ef1f84bSDavid du Colombier void
forceclosefgrp(void)2479ef1f84bSDavid du Colombier forceclosefgrp(void)
2489ef1f84bSDavid du Colombier {
2499ef1f84bSDavid du Colombier 	int i;
2509ef1f84bSDavid du Colombier 	Chan *c;
2519ef1f84bSDavid du Colombier 	Fgrp *f;
2529ef1f84bSDavid du Colombier 
2539ef1f84bSDavid du Colombier 	if(up->procctl != Proc_exitme || up->closingfgrp == nil){
2549ef1f84bSDavid du Colombier 		print("bad forceclosefgrp call");
2559ef1f84bSDavid du Colombier 		return;
2569ef1f84bSDavid du Colombier 	}
2579ef1f84bSDavid du Colombier 
2589ef1f84bSDavid du Colombier 	f = up->closingfgrp;
2599ef1f84bSDavid du Colombier 	for(i = 0; i <= f->maxfd; i++){
2609ef1f84bSDavid du Colombier 		if(c = f->fd[i]){
2619ef1f84bSDavid du Colombier 			f->fd[i] = nil;
2629ef1f84bSDavid du Colombier 			ccloseq(c);
2639ef1f84bSDavid du Colombier 		}
2649ef1f84bSDavid du Colombier 	}
2659ef1f84bSDavid du Colombier }
2669ef1f84bSDavid du Colombier 
2679ef1f84bSDavid du Colombier Mount*
newmount(Mhead * mh,Chan * to,int flag,char * spec)2689ef1f84bSDavid du Colombier newmount(Mhead *mh, Chan *to, int flag, char *spec)
2699ef1f84bSDavid du Colombier {
2709ef1f84bSDavid du Colombier 	Mount *mount;
2719ef1f84bSDavid du Colombier 
2729ef1f84bSDavid du Colombier 	mount = smalloc(sizeof(Mount));
2739ef1f84bSDavid du Colombier 	mount->to = to;
2749ef1f84bSDavid du Colombier 	mount->head = mh;
2759ef1f84bSDavid du Colombier 	incref(to);
2769ef1f84bSDavid du Colombier 	mount->mountid = incref(&mountid);
2779ef1f84bSDavid du Colombier 	mount->mflag = flag;
2789ef1f84bSDavid du Colombier 	if(spec != 0)
2799ef1f84bSDavid du Colombier 		kstrdup(&mount->spec, spec);
2809ef1f84bSDavid du Colombier 
2819ef1f84bSDavid du Colombier 	return mount;
2829ef1f84bSDavid du Colombier }
2839ef1f84bSDavid du Colombier 
2849ef1f84bSDavid du Colombier void
mountfree(Mount * mount)2859ef1f84bSDavid du Colombier mountfree(Mount *mount)
2869ef1f84bSDavid du Colombier {
2879ef1f84bSDavid du Colombier 	Mount *f;
2889ef1f84bSDavid du Colombier 
2899ef1f84bSDavid du Colombier 	while(mount != nil) {
2909ef1f84bSDavid du Colombier 		f = mount->next;
2919ef1f84bSDavid du Colombier 		cclose(mount->to);
2929ef1f84bSDavid du Colombier 		mount->mountid = 0;
2939ef1f84bSDavid du Colombier 		free(mount->spec);
2949ef1f84bSDavid du Colombier 		free(mount);
2959ef1f84bSDavid du Colombier 		mount = f;
2969ef1f84bSDavid du Colombier 	}
2979ef1f84bSDavid du Colombier }
2989ef1f84bSDavid du Colombier 
2999ef1f84bSDavid du Colombier void
resrcwait(char * reason)3009ef1f84bSDavid du Colombier resrcwait(char *reason)
3019ef1f84bSDavid du Colombier {
302*406c76faSDavid du Colombier 	ulong now;
3039ef1f84bSDavid du Colombier 	char *p;
304*406c76faSDavid du Colombier 	static ulong lastwhine;
3059ef1f84bSDavid du Colombier 
3069ef1f84bSDavid du Colombier 	if(up == nil)
3079ef1f84bSDavid du Colombier 		panic("resrcwait");
3089ef1f84bSDavid du Colombier 
3099ef1f84bSDavid du Colombier 	p = up->psstate;
3109ef1f84bSDavid du Colombier 	if(reason) {
3119ef1f84bSDavid du Colombier 		up->psstate = reason;
312*406c76faSDavid du Colombier 		now = seconds();
313*406c76faSDavid du Colombier 		/* don't tie up the console with complaints */
314*406c76faSDavid du Colombier 		if(now - lastwhine > Whinesecs) {
315*406c76faSDavid du Colombier 			lastwhine = now;
3169ef1f84bSDavid du Colombier 			print("%s\n", reason);
3179ef1f84bSDavid du Colombier 		}
318*406c76faSDavid du Colombier 	}
3199ef1f84bSDavid du Colombier 
3209ef1f84bSDavid du Colombier 	tsleep(&up->sleep, return0, 0, 300);
3219ef1f84bSDavid du Colombier 	up->psstate = p;
3229ef1f84bSDavid du Colombier }
323