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