2 #include "../port/lib.h"
6 #include "../port/error.h"
15 /* commands to kproc */
23 #define TYPE(x) (int)( (c)->qid.path & 0x7 )
24 #define SEG(x) ( ((c)->qid.path >> 3) & 0x3f )
25 #define PATH(s, t) ( ((s)<<3) | (t) )
27 typedef struct Globalseg Globalseg;
38 /* kproc to do reading and writing */
39 QLock l; /* sync kproc access */
40 Rendez cmdwait; /* where kproc waits */
41 Rendez replywait; /* where requestor waits */
50 static Globalseg *globalseg[100];
51 static Lock globalseglock;
54 Segment* (*_globalsegattach)(Proc*, char*);
55 static Segment* globalsegattach(Proc *p, char *name);
56 static int cmddone(void*);
57 static void segmentkproc(void*);
58 static void docmd(Globalseg *g, int cmd);
61 * returns with globalseg incref'd
71 if(x >= nelem(globalseg))
76 unlock(&globalseglock);
78 error("global segment disappeared");
97 segmentgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
107 q.path = PATH(0, Qtopdir);
109 devdir(c, q, "#g", 0, eve, DMDIR|0777, dp);
113 if(s >= nelem(globalseg))
116 lock(&globalseglock);
119 unlock(&globalseglock);
123 q.path = PATH(s, Qsegdir);
125 devdir(c, q, g->name, 0, g->uid, DMDIR|0777, dp);
126 unlock(&globalseglock);
132 q.path = PATH(0, Qtopdir);
134 devdir(c, q, "#g", 0, eve, DMDIR|0777, dp);
144 q.path = PATH(SEG(c), Qctl);
146 devdir(c, q, "ctl", 0, g->uid, g->perm, dp);
152 q.path = PATH(SEG(c), Qdata);
155 size = g->s->top - g->s->base;
158 devdir(c, q, "data", size, g->uid, g->perm, dp);
172 _globalsegattach = globalsegattach;
176 segmentattach(char *spec)
178 return devattach('g', spec);
182 segmentwalk(Chan *c, Chan *nc, char **name, int nname)
184 return devwalk(c, nc, name, nname, 0, 0, segmentgen);
188 segmentstat(Chan *c, uchar *db, int n)
190 return devstat(c, db, n, 0, 0, segmentgen);
198 return g->cmd == Cnone;
202 segmentopen(Chan *c, int omode)
218 devpermcheck(g->uid, g->perm, omode);
229 devpermcheck(g->uid, g->perm, omode);
231 error("segment not yet allocated");
240 kproc(g->name, segmentkproc, g);
251 panic("segmentopen");
253 c->mode = openmode(omode);
259 segmentclose(Chan *c)
261 if(TYPE(c) == Qtopdir)
268 segmentcreate(Chan *c, char *name, int omode, ulong perm)
273 if(TYPE(c) != Qtopdir)
279 if((perm & DMDIR) == 0)
283 unlock(&globalseglock);
286 lock(&globalseglock);
288 for(x = 0; x < nelem(globalseg); x++){
294 if(strcmp(g->name, name) == 0)
299 error("too many global segments");
300 g = smalloc(sizeof(Globalseg));
302 kstrdup(&g->name, name);
303 kstrdup(&g->uid, up->user);
305 globalseg[xfree] = g;
306 unlock(&globalseglock);
309 c->qid.path = PATH(x, Qsegdir);
312 c->mode = openmode(omode);
317 segmentread(Chan *c, void *a, long n, vlong voff)
322 if(c->qid.type == QTDIR)
323 return devdirread(c, a, n, (Dirtab *)0, 0L, segmentgen);
329 error("segment not yet allocated");
330 sprint(buf, "va %#lux %#lux\n", g->s->base, g->s->top-g->s->base);
331 return readstr(voff, a, n, buf);
334 if(voff > g->s->top - g->s->base)
336 if(voff + n > g->s->top - g->s->base)
337 n = g->s->top - g->s->base - voff;
339 g->off = voff + g->s->base;
340 g->data = smalloc(n);
348 memmove(a, g->data, g->dlen);
354 panic("segmentread");
356 return 0; /* not reached */
360 segmentwrite(Chan *c, void *a, long n, vlong voff)
366 if(c->qid.type == QTDIR)
373 if(strcmp(cb->f[0], "va") == 0){
375 error("already has a virtual address");
378 va = strtoul(cb->f[1], 0, 0);
379 len = strtoul(cb->f[2], 0, 0);
380 top = PGROUND(va + len);
382 len = (top - va) / BY2PG;
385 g->s = newseg(SG_SHARED, va, len);
391 if(voff + n > g->s->top - g->s->base)
394 g->off = voff + g->s->base;
395 g->data = smalloc(n);
402 memmove(g->data, a, g->dlen);
409 panic("segmentwrite");
411 return 0; /* not reached */
415 segmentwstat(Chan *c, uchar *dp, int n)
420 if(c->qid.type == QTDIR)
429 if(strcmp(g->uid, up->user) && !iseve())
431 d = smalloc(sizeof(Dir)+n);
432 n = convM2D(dp, n, &d[0], (char*)&d[1]);
433 g->perm = d->mode & 0777;
443 segmentremove(Chan *c)
448 if(TYPE(c) != Qsegdir)
450 lock(&globalseglock);
454 unlock(&globalseglock);
460 * called by segattach()
463 globalsegattach(Proc *p, char *name)
471 unlock(&globalseglock);
474 lock(&globalseglock);
475 for(x = 0; x < nelem(globalseg); x++){
477 if(g != nil && strcmp(g->name, name) == 0)
480 if(x == nelem(globalseg)){
481 unlock(&globalseglock);
485 devpermcheck(g->uid, g->perm, ORDWR);
488 error("global segment not assigned a virtual address");
489 if(isoverlap(p, s->base, s->top - s->base) != nil)
490 error("overlaps existing segment");
492 unlock(&globalseglock);
498 docmd(Globalseg *g, int cmd)
503 sleep(&g->replywait, cmddone, g);
513 return g->cmd != Cnone;
517 segmentkproc(void *arg)
523 for(sno = 0; sno < NSEG; sno++)
524 if(up->seg[sno] == nil && sno != ESEG)
527 panic("segmentkproc");
533 for(done = 0; !done;){
534 sleep(&g->cmdwait, cmdready, g);
536 strncpy(g->err, up->errstr, sizeof(g->err));
545 memmove(g->data, (char*)g->off, g->dlen);
548 memmove((char*)g->off, g->data, g->dlen);
554 wakeup(&g->replywait);
558 Dev segmentdevtab = {