]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/pgrp.c
Import sources from 2011-03-30 iso image - lib
[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         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 = 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 = 1;
64         return r;
65 }
66
67 void
68 closergrp(Rgrp *r)
69 {
70         if(decref(r) == 0)
71                 free(r);
72 }
73
74 void
75 closepgrp(Pgrp *p)
76 {
77         Mhead **h, **e, *f, *next;
78
79         if(decref(p) != 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);
159         for(m = order; m; m = m->order)
160                 m->copy->mountid = mountid.ref++;
161         unlock(&mountid);
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 = 1;
177                 return new;
178         }
179
180         lock(f);
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);
189                 free(new);
190                 error("no memory for fgrp");
191         }
192         new->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);
198                         new->fd[i] = c;
199                 }
200         }
201         unlock(f);
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) != 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);
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");
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 }