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