pgrp.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       pgrp.c (5081B)
       ---
            1 #include        "u.h"
            2 #include        "lib.h"
            3 #include        "mem.h"
            4 #include        "dat.h"
            5 #include        "fns.h"
            6 #include        "error.h"
            7 
            8 enum {
            9         Whinesecs = 10,                /* frequency of out-of-resources printing */
           10 };
           11 
           12 static Ref pgrpid;
           13 static Ref mountid;
           14 
           15 void
           16 pgrpnote(ulong noteid, char *a, long n, int flag)
           17 {
           18         Proc *p, *ep;
           19         char buf[ERRMAX];
           20 
           21         if(n >= ERRMAX-1)
           22                 error(Etoobig);
           23 
           24         memmove(buf, a, n);
           25         buf[n] = 0;
           26         p = proctab(0);
           27         ep = p+conf.nproc;
           28         for(; p < ep; p++) {
           29                 if(p->state == Dead)
           30                         continue;
           31                 if(up != p && p->noteid == noteid && p->kp == 0) {
           32                         qlock(&p->debug);
           33                         if(p->pid == 0 || p->noteid != noteid){
           34                                 qunlock(&p->debug);
           35                                 continue;
           36                         }
           37                         if(!waserror()) {
           38                                 postnote(p, 0, buf, flag);
           39                                 poperror();
           40                         }
           41                         qunlock(&p->debug);
           42                 }
           43         }
           44 }
           45 
           46 Pgrp*
           47 newpgrp(void)
           48 {
           49         Pgrp *p;
           50 
           51         p = smalloc(sizeof(Pgrp));
           52         p->ref.ref = 1;
           53         p->pgrpid = incref(&pgrpid);
           54         return p;
           55 }
           56 
           57 Rgrp*
           58 newrgrp(void)
           59 {
           60         Rgrp *r;
           61 
           62         r = smalloc(sizeof(Rgrp));
           63         r->ref.ref = 1;
           64         return r;
           65 }
           66 
           67 void
           68 closergrp(Rgrp *r)
           69 {
           70         if(decref(&r->ref) == 0)
           71                 free(r);
           72 }
           73 
           74 void
           75 closepgrp(Pgrp *p)
           76 {
           77         Mhead **h, **e, *f, *next;
           78 
           79         if(decref(&p->ref) != 0)
           80                 return;
           81 
           82         qlock(&p->debug);
           83         wlock(&p->ns);
           84         p->pgrpid = -1;
           85 
           86         e = &p->mnthash[MNTHASH];
           87         for(h = p->mnthash; h < e; h++) {
           88                 for(f = *h; f; f = next) {
           89                         wlock(&f->lock);
           90                         cclose(f->from);
           91                         mountfree(f->mount);
           92                         f->mount = nil;
           93                         next = f->hash;
           94                         wunlock(&f->lock);
           95                         putmhead(f);
           96                 }
           97         }
           98         wunlock(&p->ns);
           99         qunlock(&p->debug);
          100         free(p);
          101 }
          102 
          103 void
          104 pgrpinsert(Mount **order, Mount *m)
          105 {
          106         Mount *f;
          107 
          108         m->order = 0;
          109         if(*order == 0) {
          110                 *order = m;
          111                 return;
          112         }
          113         for(f = *order; f; f = f->order) {
          114                 if(m->mountid < f->mountid) {
          115                         m->order = f;
          116                         *order = m;
          117                         return;
          118                 }
          119                 order = &f->order;
          120         }
          121         *order = m;
          122 }
          123 
          124 /*
          125  * pgrpcpy MUST preserve the mountid allocation order of the parent group
          126  */
          127 void
          128 pgrpcpy(Pgrp *to, Pgrp *from)
          129 {
          130         int i;
          131         Mount *n, *m, **link, *order;
          132         Mhead *f, **tom, **l, *mh;
          133 
          134         wlock(&from->ns);
          135         order = 0;
          136         tom = to->mnthash;
          137         for(i = 0; i < MNTHASH; i++) {
          138                 l = tom++;
          139                 for(f = from->mnthash[i]; f; f = f->hash) {
          140                         rlock(&f->lock);
          141                         mh = newmhead(f->from);
          142                         *l = mh;
          143                         l = &mh->hash;
          144                         link = &mh->mount;
          145                         for(m = f->mount; m; m = m->next) {
          146                                 n = newmount(mh, m->to, m->mflag, m->spec);
          147                                 m->copy = n;
          148                                 pgrpinsert(&order, m);
          149                                 *link = n;
          150                                 link = &n->next;
          151                         }
          152                         runlock(&f->lock);
          153                 }
          154         }
          155         /*
          156          * Allocate mount ids in the same sequence as the parent group
          157          */
          158         lock(&mountid.lk);
          159         for(m = order; m; m = m->order)
          160                 m->copy->mountid = mountid.ref++;
          161         unlock(&mountid.lk);
          162         wunlock(&from->ns);
          163 }
          164 
          165 Fgrp*
          166 dupfgrp(Fgrp *f)
          167 {
          168         Fgrp *new;
          169         Chan *c;
          170         int i;
          171 
          172         new = smalloc(sizeof(Fgrp));
          173         if(f == nil){
          174                 new->fd = smalloc(DELTAFD*sizeof(Chan*));
          175                 new->nfd = DELTAFD;
          176                 new->ref.ref = 1;
          177                 return new;
          178         }
          179 
          180         lock(&f->ref.lk);
          181         /* Make new fd list shorter if possible, preserving quantization */
          182         new->nfd = f->maxfd+1;
          183         i = new->nfd%DELTAFD;
          184         if(i != 0)
          185                 new->nfd += DELTAFD - i;
          186         new->fd = malloc(new->nfd*sizeof(Chan*));
          187         if(new->fd == nil){
          188                 unlock(&f->ref.lk);
          189                 free(new);
          190                 error("no memory for fgrp");
          191         }
          192         new->ref.ref = 1;
          193 
          194         new->maxfd = f->maxfd;
          195         for(i = 0; i <= f->maxfd; i++) {
          196                 if((c = f->fd[i])){
          197                         incref(&c->ref);
          198                         new->fd[i] = c;
          199                 }
          200         }
          201         unlock(&f->ref.lk);
          202 
          203         return new;
          204 }
          205 
          206 void
          207 closefgrp(Fgrp *f)
          208 {
          209         int i;
          210         Chan *c;
          211 
          212         if(f == 0)
          213                 return;
          214 
          215         if(decref(&f->ref) != 0)
          216                 return;
          217 
          218         /*
          219          * If we get into trouble, forceclosefgrp
          220          * will bail us out.
          221          */
          222         up->closingfgrp = f;
          223         for(i = 0; i <= f->maxfd; i++)
          224                 if((c = f->fd[i])){
          225                         f->fd[i] = nil;
          226                         cclose(c);
          227                 }
          228         up->closingfgrp = nil;
          229 
          230         free(f->fd);
          231         free(f);
          232 }
          233 
          234 /*
          235  * Called from sleep because up is in the middle
          236  * of closefgrp and just got a kill ctl message.
          237  * This usually means that up has wedged because
          238  * of some kind of deadly embrace with mntclose
          239  * trying to talk to itself.  To break free, hand the
          240  * unclosed channels to the close queue.  Once they
          241  * are finished, the blocked cclose that we've 
          242  * interrupted will finish by itself.
          243  */
          244 void
          245 forceclosefgrp(void)
          246 {
          247         int i;
          248         Chan *c;
          249         Fgrp *f;
          250 
          251         if(up->procctl != Proc_exitme || up->closingfgrp == nil){
          252                 print("bad forceclosefgrp call");
          253                 return;
          254         }
          255 
          256         f = up->closingfgrp;
          257         for(i = 0; i <= f->maxfd; i++)
          258                 if((c = f->fd[i])){
          259                         f->fd[i] = nil;
          260                         ccloseq(c);
          261                 }
          262 }
          263 
          264 
          265 Mount*
          266 newmount(Mhead *mh, Chan *to, int flag, char *spec)
          267 {
          268         Mount *m;
          269 
          270         m = smalloc(sizeof(Mount));
          271         m->to = to;
          272         m->head = mh;
          273         incref(&to->ref);
          274         m->mountid = incref(&mountid);
          275         m->mflag = flag;
          276         if(spec != 0)
          277                 kstrdup(&m->spec, spec);
          278 
          279         return m;
          280 }
          281 
          282 void
          283 mountfree(Mount *m)
          284 {
          285         Mount *f;
          286 
          287         while(m) {
          288                 f = m->next;
          289                 cclose(m->to);
          290                 m->mountid = 0;
          291                 free(m->spec);
          292                 free(m);
          293                 m = f;
          294         }
          295 }
          296 
          297 void
          298 resrcwait(char *reason)
          299 {
          300         ulong now;
          301         char *p;
          302         static ulong lastwhine;
          303 
          304         if(up == 0)
          305                 panic("resrcwait: %s", reason);
          306 
          307         p = up->psstate;
          308         if(reason) {
          309                 up->psstate = reason;
          310                 now = seconds();
          311                 /* don't tie up the console with complaints */
          312                 if(now - lastwhine > Whinesecs) {
          313                         lastwhine = now;
          314                         print("%s\n", reason);
          315                 }
          316         }
          317 
          318         tsleep(&up->sleep, return0, 0, 300);
          319         up->psstate = p;
          320 }