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