123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "../port/error.h"
- static Ref pgrpid;
- static Ref mountid;
- void
- pgrpnote(uint32_t noteid, char *a, int32_t n, int flag)
- {
- Proc *up = externup();
- int i;
- Proc *p;
- char buf[ERRMAX];
- if(n >= ERRMAX-1)
- error(Etoobig);
- memmove(buf, a, n);
- buf[n] = 0;
- for(i = 0; (p = psincref(i)) != nil; i++){
- if(p == up || p->state == Dead || p->noteid != noteid || p->kp){
- psdecref(p);
- continue;
- }
- qlock(&p->debug);
- if(p->pid == 0 || p->noteid != noteid){
- qunlock(&p->debug);
- psdecref(p);
- continue;
- }
- if(!waserror()) {
- postnote(p, 0, buf, flag);
- poperror();
- }
- qunlock(&p->debug);
- psdecref(p);
- }
- }
- Pgrp*
- newpgrp(void)
- {
- Pgrp *p;
- p = smalloc(sizeof(Pgrp));
- p->r.ref = 1;
- p->pgrpid = incref(&pgrpid);
- return p;
- }
- Rgrp*
- newrgrp(void)
- {
- Rgrp *r;
- r = smalloc(sizeof(Rgrp));
- r->r.ref = 1;
- return r;
- }
- void
- closergrp(Rgrp *r)
- {
- if(decref(&r->r) == 0)
- free(r);
- }
- void
- closepgrp(Pgrp *p)
- {
- Mhead **h, **e, *f, *next;
- if(decref(&p->r) != 0)
- return;
- qlock(&p->debug);
- wlock(&p->ns);
- p->pgrpid = -1;
- e = &p->mnthash[MNTHASH];
- for(h = p->mnthash; h < e; h++) {
- for(f = *h; f; f = next) {
- wlock(&f->lock);
- cclose(f->from);
- mountfree(f->mount);
- f->mount = nil;
- next = f->hash;
- wunlock(&f->lock);
- putmhead(f);
- }
- }
- wunlock(&p->ns);
- qunlock(&p->debug);
- free(p);
- }
- void
- pgrpinsert(Mount **order, Mount *mount)
- {
- Mount *f;
- mount->order = 0;
- if(*order == 0) {
- *order = mount;
- return;
- }
- for(f = *order; f; f = f->order) {
- if(mount->mountid < f->mountid) {
- mount->order = f;
- *order = mount;
- return;
- }
- order = &f->order;
- }
- *order = mount;
- }
- /*
- * pgrpcpy MUST preserve the mountid allocation order of the parent group
- */
- void
- pgrpcpy(Pgrp *to, Pgrp *from)
- {
- int i;
- Mount *n, *mount, **link, *order;
- Mhead *f, **tom, **l, *mh;
- wlock(&from->ns);
- order = 0;
- tom = to->mnthash;
- for(i = 0; i < MNTHASH; i++) {
- l = tom++;
- for(f = from->mnthash[i]; f; f = f->hash) {
- rlock(&f->lock);
- mh = newmhead(f->from);
- *l = mh;
- l = &mh->hash;
- link = &mh->mount;
- for(mount = f->mount; mount != nil; mount = mount->next) {
- n = newmount(mh, mount->to, mount->mflag, mount->spec);
- mount->copy = n;
- pgrpinsert(&order, mount);
- *link = n;
- link = &n->next;
- }
- runlock(&f->lock);
- }
- }
- /*
- * Allocate mount ids in the same sequence as the parent group
- */
- lock(&mountid.l);
- for(mount = order; mount != nil; mount = mount->order)
- mount->copy->mountid = mountid.ref++;
- unlock(&mountid.l);
- wunlock(&from->ns);
- }
- Fgrp*
- dupfgrp(Fgrp *f)
- {
- Fgrp *new;
- Chan *c;
- int i;
- new = smalloc(sizeof(Fgrp));
- if(f == nil){
- new->fd = smalloc(DELTAFD*sizeof(Chan*));
- new->nfd = DELTAFD;
- new->r.ref = 1;
- return new;
- }
- lock(&f->r.l);
- /* Make new fd list shorter if possible, preserving quantization */
- new->nfd = f->maxfd+1;
- i = new->nfd%DELTAFD;
- if(i != 0)
- new->nfd += DELTAFD - i;
- new->fd = malloc(new->nfd*sizeof(Chan*));
- if(new->fd == nil){
- unlock(&f->r.l);
- free(new);
- error("no memory for fgrp");
- }
- new->r.ref = 1;
- new->maxfd = f->maxfd;
- for(i = 0; i <= f->maxfd; i++) {
- if(c = f->fd[i]){
- incref(&c->r);
- new->fd[i] = c;
- }
- }
- unlock(&f->r.l);
- return new;
- }
- void
- closefgrp(Fgrp *f)
- {
- Proc *up = externup();
- int i;
- Chan *c;
- if(f == 0)
- return;
- if(decref(&f->r) != 0)
- return;
- /*
- * If we get into trouble, forceclosefgrp
- * will bail us out.
- */
- up->closingfgrp = f;
- for(i = 0; i <= f->maxfd; i++){
- if(c = f->fd[i]){
- f->fd[i] = nil;
- cclose(c);
- }
- }
- up->closingfgrp = nil;
- free(f->fd);
- free(f);
- }
- /*
- * Called from sleep because up is in the middle
- * of closefgrp and just got a kill ctl message.
- * This usually means that up has wedged because
- * of some kind of deadly embrace with mntclose
- * trying to talk to itself. To break free, hand the
- * unclosed channels to the close queue. Once they
- * are finished, the blocked cclose that we've
- * interrupted will finish by itself.
- */
- void
- forceclosefgrp(void)
- {
- Proc *up = externup();
- int i;
- Chan *c;
- Fgrp *f;
- if(up->procctl != Proc_exitme || up->closingfgrp == nil){
- print("bad forceclosefgrp call");
- return;
- }
- f = up->closingfgrp;
- for(i = 0; i <= f->maxfd; i++){
- if(c = f->fd[i]){
- f->fd[i] = nil;
- ccloseq(c);
- }
- }
- }
- Mount*
- newmount(Mhead *mh, Chan *to, int flag, char *spec)
- {
- Mount *mount;
- mount = smalloc(sizeof(Mount));
- mount->to = to;
- mount->head = mh;
- incref(&to->r);
- mount->mountid = incref(&mountid);
- mount->mflag = flag;
- if(spec != 0)
- kstrdup(&mount->spec, spec);
- return mount;
- }
- void
- mountfree(Mount *mount)
- {
- Mount *f;
- while(mount != nil) {
- f = mount->next;
- cclose(mount->to);
- mount->mountid = 0;
- free(mount->spec);
- free(mount);
- mount = f;
- }
- }
- void
- resrcwait(char *reason)
- {
- Proc *up = externup();
- char *p;
- if(up == nil)
- panic("resrcwait");
- p = up->psstate;
- if(reason) {
- up->psstate = reason;
- print("%s\n", reason);
- }
- tsleep(&up->sleep, return0, 0, 300);
- up->psstate = p;
- }
|