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