FreeBSD/Linux Kernel Cross Reference
sys/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 }
Cache object: 0847af4591aec7c3e7716976e10b4484
|