xref: /plan9-contrib/sys/src/9/port/pgrp.c (revision 14cc0f535177405a84c5b73603a98e5db6674719)
13e12c5d1SDavid du Colombier #include	"u.h"
23e12c5d1SDavid du Colombier #include	"../port/lib.h"
33e12c5d1SDavid du Colombier #include	"mem.h"
43e12c5d1SDavid du Colombier #include	"dat.h"
53e12c5d1SDavid du Colombier #include	"fns.h"
63e12c5d1SDavid du Colombier #include	"../port/error.h"
73e12c5d1SDavid du Colombier 
8*14cc0f53SDavid du Colombier enum {
9*14cc0f53SDavid du Colombier 	Whinesecs = 10,		/* frequency of out-of-resources printing */
10*14cc0f53SDavid du Colombier };
11*14cc0f53SDavid du Colombier 
123e12c5d1SDavid du Colombier static Ref pgrpid;
133e12c5d1SDavid du Colombier static Ref mountid;
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier void
pgrpnote(ulong noteid,char * a,long n,int flag)163e12c5d1SDavid du Colombier pgrpnote(ulong noteid, char *a, long n, int flag)
173e12c5d1SDavid du Colombier {
183e12c5d1SDavid du Colombier 	Proc *p, *ep;
199a747e4fSDavid du Colombier 	char buf[ERRMAX];
203e12c5d1SDavid du Colombier 
219a747e4fSDavid du Colombier 	if(n >= ERRMAX-1)
223e12c5d1SDavid du Colombier 		error(Etoobig);
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier 	memmove(buf, a, n);
253e12c5d1SDavid du Colombier 	buf[n] = 0;
263e12c5d1SDavid du Colombier 	p = proctab(0);
273e12c5d1SDavid du Colombier 	ep = p+conf.nproc;
283e12c5d1SDavid du Colombier 	for(; p < ep; p++) {
293e12c5d1SDavid du Colombier 		if(p->state == Dead)
303e12c5d1SDavid du Colombier 			continue;
317dd7cddfSDavid du Colombier 		if(up != p && p->noteid == noteid && p->kp == 0) {
323e12c5d1SDavid du Colombier 			qlock(&p->debug);
333e12c5d1SDavid du Colombier 			if(p->pid == 0 || p->noteid != noteid){
343e12c5d1SDavid du Colombier 				qunlock(&p->debug);
353e12c5d1SDavid du Colombier 				continue;
363e12c5d1SDavid du Colombier 			}
373e12c5d1SDavid du Colombier 			if(!waserror()) {
383e12c5d1SDavid du Colombier 				postnote(p, 0, buf, flag);
393e12c5d1SDavid du Colombier 				poperror();
403e12c5d1SDavid du Colombier 			}
413e12c5d1SDavid du Colombier 			qunlock(&p->debug);
423e12c5d1SDavid du Colombier 		}
433e12c5d1SDavid du Colombier 	}
443e12c5d1SDavid du Colombier }
453e12c5d1SDavid du Colombier 
463e12c5d1SDavid du Colombier Pgrp*
newpgrp(void)473e12c5d1SDavid du Colombier newpgrp(void)
483e12c5d1SDavid du Colombier {
493e12c5d1SDavid du Colombier 	Pgrp *p;
503e12c5d1SDavid du Colombier 
513e12c5d1SDavid du Colombier 	p = smalloc(sizeof(Pgrp));
523e12c5d1SDavid du Colombier 	p->ref = 1;
533e12c5d1SDavid du Colombier 	p->pgrpid = incref(&pgrpid);
543e12c5d1SDavid du Colombier 	return p;
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier 
577dd7cddfSDavid du Colombier Rgrp*
newrgrp(void)587dd7cddfSDavid du Colombier newrgrp(void)
597dd7cddfSDavid du Colombier {
607dd7cddfSDavid du Colombier 	Rgrp *r;
617dd7cddfSDavid du Colombier 
627dd7cddfSDavid du Colombier 	r = smalloc(sizeof(Rgrp));
637dd7cddfSDavid du Colombier 	r->ref = 1;
647dd7cddfSDavid du Colombier 	return r;
657dd7cddfSDavid du Colombier }
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier void
closergrp(Rgrp * r)687dd7cddfSDavid du Colombier closergrp(Rgrp *r)
697dd7cddfSDavid du Colombier {
707dd7cddfSDavid du Colombier 	if(decref(r) == 0)
717dd7cddfSDavid du Colombier 		free(r);
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier 
743e12c5d1SDavid du Colombier void
closepgrp(Pgrp * p)753e12c5d1SDavid du Colombier closepgrp(Pgrp *p)
763e12c5d1SDavid du Colombier {
773e12c5d1SDavid du Colombier 	Mhead **h, **e, *f, *next;
783e12c5d1SDavid du Colombier 
797dd7cddfSDavid du Colombier 	if(decref(p) != 0)
807dd7cddfSDavid du Colombier 		return;
817dd7cddfSDavid du Colombier 
823e12c5d1SDavid du Colombier 	qlock(&p->debug);
837dd7cddfSDavid du Colombier 	wlock(&p->ns);
843e12c5d1SDavid du Colombier 	p->pgrpid = -1;
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier 	e = &p->mnthash[MNTHASH];
873e12c5d1SDavid du Colombier 	for(h = p->mnthash; h < e; h++) {
883e12c5d1SDavid du Colombier 		for(f = *h; f; f = next) {
897dd7cddfSDavid du Colombier 			wlock(&f->lock);
907dd7cddfSDavid du Colombier 			cclose(f->from);
913e12c5d1SDavid du Colombier 			mountfree(f->mount);
927dd7cddfSDavid du Colombier 			f->mount = nil;
933e12c5d1SDavid du Colombier 			next = f->hash;
947dd7cddfSDavid du Colombier 			wunlock(&f->lock);
957dd7cddfSDavid du Colombier 			putmhead(f);
963e12c5d1SDavid du Colombier 		}
973e12c5d1SDavid du Colombier 	}
987dd7cddfSDavid du Colombier 	wunlock(&p->ns);
993e12c5d1SDavid du Colombier 	qunlock(&p->debug);
1003e12c5d1SDavid du Colombier 	free(p);
1013e12c5d1SDavid du Colombier }
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier void
pgrpinsert(Mount ** order,Mount * m)1047dd7cddfSDavid du Colombier pgrpinsert(Mount **order, Mount *m)
1057dd7cddfSDavid du Colombier {
1067dd7cddfSDavid du Colombier 	Mount *f;
1077dd7cddfSDavid du Colombier 
1087dd7cddfSDavid du Colombier 	m->order = 0;
1097dd7cddfSDavid du Colombier 	if(*order == 0) {
1107dd7cddfSDavid du Colombier 		*order = m;
1117dd7cddfSDavid du Colombier 		return;
1127dd7cddfSDavid du Colombier 	}
1137dd7cddfSDavid du Colombier 	for(f = *order; f; f = f->order) {
1147dd7cddfSDavid du Colombier 		if(m->mountid < f->mountid) {
1157dd7cddfSDavid du Colombier 			m->order = f;
1167dd7cddfSDavid du Colombier 			*order = m;
1177dd7cddfSDavid du Colombier 			return;
1187dd7cddfSDavid du Colombier 		}
1197dd7cddfSDavid du Colombier 		order = &f->order;
1207dd7cddfSDavid du Colombier 	}
1217dd7cddfSDavid du Colombier 	*order = m;
1223e12c5d1SDavid du Colombier }
1233e12c5d1SDavid du Colombier 
1247dd7cddfSDavid du Colombier /*
1257dd7cddfSDavid du Colombier  * pgrpcpy MUST preserve the mountid allocation order of the parent group
1267dd7cddfSDavid du Colombier  */
1273e12c5d1SDavid du Colombier void
pgrpcpy(Pgrp * to,Pgrp * from)1283e12c5d1SDavid du Colombier pgrpcpy(Pgrp *to, Pgrp *from)
1293e12c5d1SDavid du Colombier {
1307dd7cddfSDavid du Colombier 	int i;
1317dd7cddfSDavid du Colombier 	Mount *n, *m, **link, *order;
1327dd7cddfSDavid du Colombier 	Mhead *f, **tom, **l, *mh;
1333e12c5d1SDavid du Colombier 
1347dd7cddfSDavid du Colombier 	wlock(&from->ns);
1357dd7cddfSDavid du Colombier 	order = 0;
1363e12c5d1SDavid du Colombier 	tom = to->mnthash;
1377dd7cddfSDavid du Colombier 	for(i = 0; i < MNTHASH; i++) {
1383e12c5d1SDavid du Colombier 		l = tom++;
1397dd7cddfSDavid du Colombier 		for(f = from->mnthash[i]; f; f = f->hash) {
1407dd7cddfSDavid du Colombier 			rlock(&f->lock);
1413ff48bf5SDavid du Colombier 			mh = newmhead(f->from);
1423e12c5d1SDavid du Colombier 			*l = mh;
1433e12c5d1SDavid du Colombier 			l = &mh->hash;
1443e12c5d1SDavid du Colombier 			link = &mh->mount;
1453e12c5d1SDavid du Colombier 			for(m = f->mount; m; m = m->next) {
1469a747e4fSDavid du Colombier 				n = newmount(mh, m->to, m->mflag, m->spec);
1477dd7cddfSDavid du Colombier 				m->copy = n;
1487dd7cddfSDavid du Colombier 				pgrpinsert(&order, m);
1493e12c5d1SDavid du Colombier 				*link = n;
1503e12c5d1SDavid du Colombier 				link = &n->next;
1513e12c5d1SDavid du Colombier 			}
1527dd7cddfSDavid du Colombier 			runlock(&f->lock);
1533e12c5d1SDavid du Colombier 		}
1543e12c5d1SDavid du Colombier 	}
1557dd7cddfSDavid du Colombier 	/*
1567dd7cddfSDavid du Colombier 	 * Allocate mount ids in the same sequence as the parent group
1577dd7cddfSDavid du Colombier 	 */
158fe853e23SDavid du Colombier 	lock(&mountid);
1597dd7cddfSDavid du Colombier 	for(m = order; m; m = m->order)
1607dd7cddfSDavid du Colombier 		m->copy->mountid = mountid.ref++;
161fe853e23SDavid du Colombier 	unlock(&mountid);
1627dd7cddfSDavid du Colombier 	wunlock(&from->ns);
1633e12c5d1SDavid du Colombier }
1643e12c5d1SDavid du Colombier 
1653e12c5d1SDavid du Colombier Fgrp*
dupfgrp(Fgrp * f)1663e12c5d1SDavid du Colombier dupfgrp(Fgrp *f)
1673e12c5d1SDavid du Colombier {
1683e12c5d1SDavid du Colombier 	Fgrp *new;
1693e12c5d1SDavid du Colombier 	Chan *c;
1703e12c5d1SDavid du Colombier 	int i;
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier 	new = smalloc(sizeof(Fgrp));
1737dd7cddfSDavid du Colombier 	if(f == nil){
1747dd7cddfSDavid du Colombier 		new->fd = smalloc(DELTAFD*sizeof(Chan*));
1757dd7cddfSDavid du Colombier 		new->nfd = DELTAFD;
1763e12c5d1SDavid du Colombier 		new->ref = 1;
1777dd7cddfSDavid du Colombier 		return new;
1787dd7cddfSDavid du Colombier 	}
1793e12c5d1SDavid du Colombier 
1803e12c5d1SDavid du Colombier 	lock(f);
1817dd7cddfSDavid du Colombier 	/* Make new fd list shorter if possible, preserving quantization */
1827dd7cddfSDavid du Colombier 	new->nfd = f->maxfd+1;
1837dd7cddfSDavid du Colombier 	i = new->nfd%DELTAFD;
1847dd7cddfSDavid du Colombier 	if(i != 0)
1857dd7cddfSDavid du Colombier 		new->nfd += DELTAFD - i;
1867dd7cddfSDavid du Colombier 	new->fd = malloc(new->nfd*sizeof(Chan*));
187dc5a79c1SDavid du Colombier 	if(new->fd == nil){
1887dd7cddfSDavid du Colombier 		unlock(f);
189dc5a79c1SDavid du Colombier 		free(new);
1907dd7cddfSDavid du Colombier 		error("no memory for fgrp");
1917dd7cddfSDavid du Colombier 	}
1927dd7cddfSDavid du Colombier 	new->ref = 1;
1937dd7cddfSDavid du Colombier 
1943e12c5d1SDavid du Colombier 	new->maxfd = f->maxfd;
1953e12c5d1SDavid du Colombier 	for(i = 0; i <= f->maxfd; i++) {
1963e12c5d1SDavid du Colombier 		if(c = f->fd[i]){
1973e12c5d1SDavid du Colombier 			incref(c);
1983e12c5d1SDavid du Colombier 			new->fd[i] = c;
1993e12c5d1SDavid du Colombier 		}
2003e12c5d1SDavid du Colombier 	}
2013e12c5d1SDavid du Colombier 	unlock(f);
2023e12c5d1SDavid du Colombier 
2033e12c5d1SDavid du Colombier 	return new;
2043e12c5d1SDavid du Colombier }
2053e12c5d1SDavid du Colombier 
2063e12c5d1SDavid du Colombier void
closefgrp(Fgrp * f)2073e12c5d1SDavid du Colombier closefgrp(Fgrp *f)
2083e12c5d1SDavid du Colombier {
2093e12c5d1SDavid du Colombier 	int i;
2103e12c5d1SDavid du Colombier 	Chan *c;
2113e12c5d1SDavid du Colombier 
2127dd7cddfSDavid du Colombier 	if(f == 0)
2137dd7cddfSDavid du Colombier 		return;
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier 	if(decref(f) != 0)
2167dd7cddfSDavid du Colombier 		return;
2177dd7cddfSDavid du Colombier 
2182cca75a1SDavid du Colombier 	/*
2192cca75a1SDavid du Colombier 	 * If we get into trouble, forceclosefgrp
2202cca75a1SDavid du Colombier 	 * will bail us out.
2212cca75a1SDavid du Colombier 	 */
2222cca75a1SDavid du Colombier 	up->closingfgrp = f;
2233e12c5d1SDavid du Colombier 	for(i = 0; i <= f->maxfd; i++)
2242cca75a1SDavid du Colombier 		if(c = f->fd[i]){
2252cca75a1SDavid du Colombier 			f->fd[i] = nil;
2267dd7cddfSDavid du Colombier 			cclose(c);
2272cca75a1SDavid du Colombier 		}
2282cca75a1SDavid du Colombier 	up->closingfgrp = nil;
2293e12c5d1SDavid du Colombier 
2307dd7cddfSDavid du Colombier 	free(f->fd);
2313e12c5d1SDavid du Colombier 	free(f);
2323e12c5d1SDavid du Colombier }
2333e12c5d1SDavid du Colombier 
2342cca75a1SDavid du Colombier /*
2352cca75a1SDavid du Colombier  * Called from sleep because up is in the middle
2362cca75a1SDavid du Colombier  * of closefgrp and just got a kill ctl message.
2372cca75a1SDavid du Colombier  * This usually means that up has wedged because
2382cca75a1SDavid du Colombier  * of some kind of deadly embrace with mntclose
2392cca75a1SDavid du Colombier  * trying to talk to itself.  To break free, hand the
2402cca75a1SDavid du Colombier  * unclosed channels to the close queue.  Once they
2412cca75a1SDavid du Colombier  * are finished, the blocked cclose that we've
2422cca75a1SDavid du Colombier  * interrupted will finish by itself.
2432cca75a1SDavid du Colombier  */
2442cca75a1SDavid du Colombier void
forceclosefgrp(void)2452cca75a1SDavid du Colombier forceclosefgrp(void)
2462cca75a1SDavid du Colombier {
2472cca75a1SDavid du Colombier 	int i;
2482cca75a1SDavid du Colombier 	Chan *c;
2492cca75a1SDavid du Colombier 	Fgrp *f;
2502cca75a1SDavid du Colombier 
2512cca75a1SDavid du Colombier 	if(up->procctl != Proc_exitme || up->closingfgrp == nil){
2522cca75a1SDavid du Colombier 		print("bad forceclosefgrp call");
2532cca75a1SDavid du Colombier 		return;
2542cca75a1SDavid du Colombier 	}
2552cca75a1SDavid du Colombier 
2562cca75a1SDavid du Colombier 	f = up->closingfgrp;
2572cca75a1SDavid du Colombier 	for(i = 0; i <= f->maxfd; i++)
2582cca75a1SDavid du Colombier 		if(c = f->fd[i]){
2592cca75a1SDavid du Colombier 			f->fd[i] = nil;
2602cca75a1SDavid du Colombier 			ccloseq(c);
2612cca75a1SDavid du Colombier 		}
2622cca75a1SDavid du Colombier }
2632cca75a1SDavid du Colombier 
2642cca75a1SDavid du Colombier 
2653e12c5d1SDavid du Colombier Mount*
newmount(Mhead * mh,Chan * to,int flag,char * spec)2667dd7cddfSDavid du Colombier newmount(Mhead *mh, Chan *to, int flag, char *spec)
2673e12c5d1SDavid du Colombier {
2683e12c5d1SDavid du Colombier 	Mount *m;
2693e12c5d1SDavid du Colombier 
2703e12c5d1SDavid du Colombier 	m = smalloc(sizeof(Mount));
2713e12c5d1SDavid du Colombier 	m->to = to;
2723e12c5d1SDavid du Colombier 	m->head = mh;
2733e12c5d1SDavid du Colombier 	incref(to);
2743e12c5d1SDavid du Colombier 	m->mountid = incref(&mountid);
2759a747e4fSDavid du Colombier 	m->mflag = flag;
2767dd7cddfSDavid du Colombier 	if(spec != 0)
2779a747e4fSDavid du Colombier 		kstrdup(&m->spec, spec);
2787dd7cddfSDavid du Colombier 
2793e12c5d1SDavid du Colombier 	return m;
2803e12c5d1SDavid du Colombier }
2813e12c5d1SDavid du Colombier 
2823e12c5d1SDavid du Colombier void
mountfree(Mount * m)2833e12c5d1SDavid du Colombier mountfree(Mount *m)
2843e12c5d1SDavid du Colombier {
2853e12c5d1SDavid du Colombier 	Mount *f;
2863e12c5d1SDavid du Colombier 
2873e12c5d1SDavid du Colombier 	while(m) {
2883e12c5d1SDavid du Colombier 		f = m->next;
2897dd7cddfSDavid du Colombier 		cclose(m->to);
2907dd7cddfSDavid du Colombier 		m->mountid = 0;
2919a747e4fSDavid du Colombier 		free(m->spec);
2923e12c5d1SDavid du Colombier 		free(m);
2933e12c5d1SDavid du Colombier 		m = f;
2943e12c5d1SDavid du Colombier 	}
2953e12c5d1SDavid du Colombier }
2963e12c5d1SDavid du Colombier 
2973e12c5d1SDavid du Colombier void
resrcwait(char * reason)2983e12c5d1SDavid du Colombier resrcwait(char *reason)
2993e12c5d1SDavid du Colombier {
300*14cc0f53SDavid du Colombier 	ulong now;
3013e12c5d1SDavid du Colombier 	char *p;
302*14cc0f53SDavid du Colombier 	static ulong lastwhine;
3033e12c5d1SDavid du Colombier 
3047dd7cddfSDavid du Colombier 	if(up == 0)
3053e12c5d1SDavid du Colombier 		panic("resrcwait");
3063e12c5d1SDavid du Colombier 
3077dd7cddfSDavid du Colombier 	p = up->psstate;
3087dd7cddfSDavid du Colombier 	if(reason) {
3097dd7cddfSDavid du Colombier 		up->psstate = reason;
310*14cc0f53SDavid du Colombier 		now = seconds();
311*14cc0f53SDavid du Colombier 		/* don't tie up the console with complaints */
312*14cc0f53SDavid du Colombier 		if(now - lastwhine > Whinesecs) {
313*14cc0f53SDavid du Colombier 			lastwhine = now;
3147dd7cddfSDavid du Colombier 			print("%s\n", reason);
3157dd7cddfSDavid du Colombier 		}
316*14cc0f53SDavid du Colombier 	}
3177dd7cddfSDavid du Colombier 
3187dd7cddfSDavid du Colombier 	tsleep(&up->sleep, return0, 0, 300);
3197dd7cddfSDavid du Colombier 	up->psstate = p;
3203e12c5d1SDavid du Colombier }
321