]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/pgrp.c
pc kernel: fix wrong simd exception mask (fixes go bootstrap)
[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;
71         Mount *m;
72
73         if(decref(p))
74                 return;
75
76         e = &p->mnthash[MNTHASH];
77         for(h = p->mnthash; h < e; h++) {
78                 while((f = *h) != nil){
79                         *h = f->hash;
80                         wlock(&f->lock);
81                         m = f->mount;
82                         f->mount = nil;
83                         wunlock(&f->lock);
84                         mountfree(m);
85                         putmhead(f);
86                 }
87         }
88         free(p);
89 }
90
91 void
92 pgrpinsert(Mount **order, Mount *m)
93 {
94         Mount *f;
95
96         m->order = nil;
97         if(*order == nil) {
98                 *order = m;
99                 return;
100         }
101         for(f = *order; f != nil; f = f->order) {
102                 if(m->mountid < f->mountid) {
103                         m->order = f;
104                         *order = m;
105                         return;
106                 }
107                 order = &f->order;
108         }
109         *order = m;
110 }
111
112 /*
113  * pgrpcpy MUST preserve the mountid allocation order of the parent group
114  */
115 void
116 pgrpcpy(Pgrp *to, Pgrp *from)
117 {
118         Mount *n, *m, **link, *order;
119         Mhead *f, **tom, **l, *mh;
120         int i;
121
122         wlock(&to->ns);
123         rlock(&from->ns);
124         order = nil;
125         tom = to->mnthash;
126         for(i = 0; i < MNTHASH; i++) {
127                 l = tom++;
128                 for(f = from->mnthash[i]; f != nil; f = f->hash) {
129                         rlock(&f->lock);
130                         mh = newmhead(f->from);
131                         *l = mh;
132                         l = &mh->hash;
133                         link = &mh->mount;
134                         for(m = f->mount; m != nil; m = m->next) {
135                                 n = smalloc(sizeof(Mount));
136                                 n->mountid = m->mountid;
137                                 n->mflag = m->mflag;
138                                 n->to = m->to;
139                                 incref(n->to);
140                                 if(m->spec != nil)
141                                         kstrdup(&n->spec, m->spec);
142                                 pgrpinsert(&order, n);
143                                 *link = n;
144                                 link = &n->next;
145                         }
146                         runlock(&f->lock);
147                 }
148         }
149         /*
150          * Allocate mount ids in the same sequence as the parent group
151          */
152         for(m = order; m != nil; m = m->order)
153                 m->mountid = incref(&mountid);
154         runlock(&from->ns);
155         wunlock(&to->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]) != nil){
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 == nil || decref(f))
206                 return;
207
208         /*
209          * If we get into trouble, forceclosefgrp
210          * will bail us out.
211          */
212         up->closingfgrp = f;
213         for(i = 0; i <= f->maxfd; i++)
214                 if((c = f->fd[i]) != nil){
215                         f->fd[i] = nil;
216                         cclose(c);
217                 }
218         up->closingfgrp = nil;
219
220         free(f->fd);
221         free(f);
222 }
223
224 /*
225  * Called from interrupted() because up is in the middle
226  * of closefgrp and just got a kill ctl message.
227  * This usually means that up has wedged because
228  * of some kind of deadly embrace with mntclose
229  * trying to talk to itself.  To break free, hand the
230  * unclosed channels to the close queue.  Once they
231  * are finished, the blocked cclose that we've 
232  * interrupted will finish by itself.
233  */
234 void
235 forceclosefgrp(void)
236 {
237         int i;
238         Chan *c;
239         Fgrp *f;
240
241         if(up->procctl != Proc_exitme || up->closingfgrp == nil){
242                 print("bad forceclosefgrp call");
243                 return;
244         }
245
246         f = up->closingfgrp;
247         for(i = 0; i <= f->maxfd; i++)
248                 if((c = f->fd[i]) != nil){
249                         f->fd[i] = nil;
250                         ccloseq(c);
251                 }
252 }
253
254
255 Mount*
256 newmount(Chan *to, int flag, char *spec)
257 {
258         Mount *m;
259
260         m = smalloc(sizeof(Mount));
261         m->to = to;
262         incref(to);
263         m->mountid = incref(&mountid);
264         m->mflag = flag;
265         if(spec != nil)
266                 kstrdup(&m->spec, spec);
267
268         return m;
269 }
270
271 void
272 mountfree(Mount *m)
273 {
274         Mount *f;
275
276         while((f = m) != nil) {
277                 m = m->next;
278                 cclose(f->to);
279                 free(f->spec);
280                 free(f);
281         }
282 }
283
284 void
285 resrcwait(char *reason)
286 {
287         static ulong lastwhine;
288         ulong now;
289         char *p;
290
291         if(up == nil)
292                 panic("resrcwait");
293
294         p = up->psstate;
295         if(reason != nil) {
296                 if(waserror()){
297                         up->psstate = p;
298                         nexterror();
299                 }
300                 up->psstate = reason;
301                 now = seconds();
302                 /* don't tie up the console with complaints */
303                 if(now - lastwhine > Whinesecs) {
304                         lastwhine = now;
305                         print("%s\n", reason);
306                 }
307         }
308         tsleep(&up->sleep, return0, 0, 100+nrand(200));
309         if(reason != nil) {
310                 up->psstate = p;
311                 poperror();
312         }
313 }