Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}