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