vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | 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 }