From 6e1a0b8aa22f1a085d8a24c83a6e3f90c6c34a58 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 23 Jun 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-06-23 --- gnot/devincon.c | 24 +- gnot/main.c | 6 +- pc/devincon.c | 12 +- port/alloc.c | 13 +- port/devarp.c | 2 +- port/devdk.c | 211 ++++------- port/devenv.c | 382 ++++++------------- port/devip.c | 8 +- port/devlance.c | 10 +- port/devpipe.c | 6 +- port/devscc.c | 2 +- port/ipdat.h | 2 +- port/net.c | 69 +++- port/pgrp.c | 69 ++-- port/portdat.h | 28 +- port/portfns.h | 14 +- port/stasync.c | 51 ++- port/stip.c | 2 +- port/stream.c | 972 +++++++++++++++++++++++------------------------- port/sturp.c | 48 ++- port/sysproc.c | 20 +- power/conf.h | 9 +- power/dat.h | 8 - power/devhs.c | 13 +- power/main.c | 7 - ss/dat.h | 10 - ss/main.c | 13 +- 27 files changed, 883 insertions(+), 1128 deletions(-) diff --git a/gnot/devincon.c b/gnot/devincon.c index 7252d37ed92cd7a05a682c60207029b593dfb064..d31c344632c7e77b72db1df1d32ca09d60834ac2 100644 --- a/gnot/devincon.c +++ b/gnot/devincon.c @@ -409,7 +409,7 @@ inconread(Chan *c, void *buf, long n, ulong offset) i = &incon[c->dev]; sprint(b, "in: %d\nout: %d\noverflow: %d\ncrc: %d\nwait: %d\n", i->in, i->out, i->overflow, i->crc, i->wait); - return stringread(buf, n, b, offset); + return readstr(offset, buf, n, b); } else return streamread(c, buf, n); } @@ -525,6 +525,13 @@ inconoput(Queue *q, Block *bp) freeb(bp); return; } + if(BLEN(bp) < 3){ + bp = pullup(bp, 3); + if(bp == 0){ + print("inconoput pullup failed\n"); + return; + } + } /* * get a whole message before handing bytes to the device @@ -542,11 +549,6 @@ inconoput(Queue *q, Block *bp) * parse message */ bp = getq(q); - if(bp->wptr - bp->rptr < 3){ - freemsg(q, bp); - qunlock(&ip->xmit); - return; - } chan = bp->rptr[0] | (bp->rptr[1]<<8); ctl = bp->rptr[2]; bp->rptr += 3; @@ -767,15 +769,15 @@ nextin(Incon *ip, unsigned int c) int next; bp = ip->inb[ip->wi]; - bp->base[0] = ip->chan; - bp->base[1] = ip->chan>>8; - bp->base[2] = c; + bp->rptr[0] = ip->chan; + bp->rptr[1] = ip->chan>>8; + bp->rptr[2] = c; if(incondebug) print("<-(%d)%uo %d\n", ip->chan, c, bp->wptr-bp->rptr); next = (ip->wi+1)%Nin; if(next == ip->ri){ - bp->wptr = bp->base+3; + bp->wptr = bp->rptr+3; return bp; } ip->wi = next; @@ -862,7 +864,7 @@ rdpackets(Incon *ip) } } bp->wptr = p; - if(bp->wptr != bp->base+3) + if(bp->wptr != bp->rptr+3) nextin(ip, 0); if(first != ip->wi)/**/ diff --git a/gnot/main.c b/gnot/main.c index c6242093bcca767165e04a4fdfc8b294bef3e64c..f3d0cdc84891929e83d70433f49002607c601f75 100644 --- a/gnot/main.c +++ b/gnot/main.c @@ -161,8 +161,10 @@ userinit(void) p = newproc(); p->pgrp = newpgrp(); - p->egrp = newegrp(); - p->fgrp = newfgrp(); + p->egrp = smalloc(sizeof(Egrp)); + p->egrp->ref = 1; + p->fgrp = smalloc(sizeof(Fgrp)); + p->fgrp->ref = 1; p->procmode = 0640; strcpy(p->text, "*init*"); diff --git a/pc/devincon.c b/pc/devincon.c index a66eeb4d4b200e4184366c08c5f8c4a9a671a0b0..06a2a742983812b395be2ddb22e67941d652be34 100644 --- a/pc/devincon.c +++ b/pc/devincon.c @@ -730,6 +730,13 @@ inconoput(Queue *q, Block *bp) freeb(bp); return; } + if(BLEN(bp) < 3){ + bp = pullup(bp, 3); + if(bp == 0){ + print("inconoput pullup failed\n"); + return; + } + } /* * get a whole message before handing bytes to the device @@ -747,11 +754,6 @@ inconoput(Queue *q, Block *bp) * parse message */ bp = getq(q); - if(bp->wptr - bp->rptr < 3){ - freemsg(q, bp); - qunlock(&ip->xmit); - return; - } chan = bp->rptr[0] | (bp->rptr[1]<<8); ctl = bp->rptr[2]; bp->rptr += 3; diff --git a/port/alloc.c b/port/alloc.c index 341d594adadeb6fcf45d9153f40fb604a0ed1109..c8ebcc3c7372618e82be0feb7407bf591403b39b 100644 --- a/port/alloc.c +++ b/port/alloc.c @@ -166,11 +166,11 @@ xalloc(ulong size) h->link = xlists.flist; xlists.flist = h; } + unlock(&xlists); p = KADDR(p); memset(p, 0, size); p->magix = Magichole; p->size = size; - unlock(&xlists); return p->data; } l = &h->link; @@ -298,6 +298,17 @@ smalloc(ulong size) return p; } +int +msize(void *ptr) +{ + Bucket *bp; + + bp = (Bucket*)((ulong)ptr - bdatoff); + if(bp->magic != Magic2n) + panic("msize"); + return 1<size; +} + void free(void *ptr) { diff --git a/port/devarp.c b/port/devarp.c index 16024a80d5871d9a5d3126153a8a56cb46841a68..aeb0c35fbc096b03382c4871c9898019d32038fc 100644 --- a/port/devarp.c +++ b/port/devarp.c @@ -240,7 +240,7 @@ arpread(Chan *c, void *a, long n, ulong offset) sprint(buf, "hits: %d miss: %d failed: %d\n", arpstats.hit, arpstats.miss, arpstats.failed); - return stringread(a, n, buf, offset); + return readstr(offset, a, n, buf); default: n=0; break; diff --git a/port/devdk.c b/port/devdk.c index abe8a908ea475a2061bfb5181c9e1df329cd516a..1a4181258a2065ce0d0b47f08f6e020d0d3247ac 100644 --- a/port/devdk.c +++ b/port/devdk.c @@ -15,7 +15,7 @@ typedef struct Line Line; typedef struct Dk Dk; enum { - Maxlines = 256, + Maxdk = 4, }; /* @@ -84,6 +84,7 @@ struct Dkmsg { struct Line { QLock; + Netprot; /* stat info */ int lineno; Rendez r; /* wait here for dial */ int state; /* dial state */ @@ -104,11 +105,13 @@ struct Line { * dkmux line discipline is pushed onto. */ struct Dk { - QLock; - Lock; + QLock netlock; + Network net; + + QLock csclock; Chan *csc; - int ref; + Lock; int opened; char name[64]; /* dk name */ @@ -122,10 +125,6 @@ struct Dk { Rendez timer; int closeall; /* set when we receive a closeall message */ Rendez closeallr; /* wait here for a closeall */ - Network net; - Netprot *prot; - - Block *alloc; /* blocks containing Line structs */ }; static Dk *dk; static Lock dklock; @@ -209,7 +208,6 @@ extern Qinfo dkinfo; * the datakit multiplexor stream module definition */ static void dkmuxopen(Queue *, Stream *); -static void dkmuxclose(Queue *); static void dkmuxoput(Queue *, Block *); static void dkmuxiput(Queue *, Block *); Qinfo dkmuxinfo = @@ -217,14 +215,14 @@ Qinfo dkmuxinfo = dkmuxiput, dkmuxoput, dkmuxopen, - dkmuxclose, + 0, "dkmux" }; /* * Look for a dk struct with a name. If none exists, create one. */ -static Dk * +static Dk* dkalloc(char *name, int ncsc, int lines) { Dk *dp; @@ -234,12 +232,12 @@ dkalloc(char *name, int ncsc, int lines) lock(&dklock); freep = 0; - for(dp = dk; dp < &dk[conf.dkif]; dp++){ + for(dp = dk; dp < &dk[Maxdk]; dp++){ if(strcmp(name, dp->name) == 0){ unlock(&dklock); return dp; } - if(dp->name[0] == 0 && dp->ref == 0) + if(dp->name[0] == 0) freep = dp; } if(freep == 0 || lines == 0){ @@ -247,9 +245,6 @@ dkalloc(char *name, int ncsc, int lines) error(Enoifc); } - /* - * init the structures - */ dp = freep; dp->opened = 0; dp->s = 0; @@ -258,18 +253,10 @@ dkalloc(char *name, int ncsc, int lines) strncpy(dp->name, name, sizeof(freep->name)); /* - * allocate memory for line structures + * allocate memory for array of pointers to lines. + * line structures are allocated as needed. */ - dp->linep = (Line **)xalloc(sizeof(Line*) * dp->lines); - if(dp->linep == 0) - error(Enomem); - lp = xalloc(dp->lines*sizeof(Line)); - if(lp == 0) - error(Enomem); - for(i = 0; i < dp->lines; i++) { - lp->lineno = i; - dp->linep[i] = lp++; - } + dp->linep = smalloc(sizeof(Line*) * dp->lines); /* * fill in the network structure @@ -280,7 +267,6 @@ dkalloc(char *name, int ncsc, int lines) dp->net.protop = &urpinfo; dp->net.listen = dklisten; dp->net.clone = dkcloneline; - dp->net.prot = dp->prot; dp->net.ninfo = 5; dp->net.info[0].name = "addr"; dp->net.info[0].fill = dkfilladdr; @@ -298,50 +284,42 @@ dkalloc(char *name, int ncsc, int lines) } /* - * a new dkmux. hold the stream in place so it can never be closed down. + * allocate a line if it doesn't exist */ -static void -dkmuxopen(Queue *q, Stream *s) +static Line* +linealloc(Dk *dp, int lineno, int dolock) { - RD(q)->ptr = s; - WR(q)->ptr = 0; + Line *lp; - s->opens++; /* Hold this queue in place */ - s->inuse++; + if(dp->opened == 0) + error(Enoifc); + if(dolock) + qlock(&dp->netlock); + if(lineno > dp->lines) + panic("linealloc"); + lp = dp->linep[lineno]; + if(lp == 0){ + lp = smalloc(sizeof(Line)); + lp->lineno = lineno; + netadd(&dp->net, lp, lineno); + dp->linep[lineno] = lp; + } + if(dolock) + qunlock(&dp->netlock); + return lp; } /* - * close down a dkmux, this shouldn't happen + * a new dkmux. hold the stream in place so it can never be closed down. */ static void -dkmuxclose(Queue *q) +dkmuxopen(Queue *q, Stream *s) { - Dk *dp; - int i; - - dp = WR(q)->ptr; - if(dp == 0) - return; - dp->name[0] = 0; - - /* - * disallow new dkstopens() on this line. - * the lock syncs with dkstopen(). - */ - lock(dp); - dp->opened = 0; - unlock(dp); - - /* - * hang up all datakit connections - */ - for(i=dp->ncsc; i < dp->lines; i++) - dkhangup(dp->linep[i]); + RD(q)->ptr = s; + WR(q)->ptr = 0; - /* - * wakeup the timer so it can die - */ - wakeup(&dp->timer); + s->opens++; /* Hold this queue in place */ + s->inuse++; } /* @@ -399,8 +377,8 @@ dkmuxiput(Queue *q, Block *bp) return; } - lp = dp->linep[line]; - if(canqlock(lp)){ + lp = linealloc(dp, line, 1); + if(lp && canqlock(lp)){ if(lp->rq) PUTNEXT(lp->rq, bp); else{ @@ -442,13 +420,6 @@ dkstopen(Queue *q, Stream *s) dp = &dk[s->dev]; q->other->ptr = q->ptr = lp = dp->linep[s->id]; lp->dp = dp; - lock(dp); - dp->ref++; - if(dp->opened==0 || streamenter(dp->s)<0){ - unlock(dp); - error(Ehungup); - } - unlock(dp); lp->rq = q; if(lp->state==Lclosed) lp->state = Lopened; @@ -475,11 +446,6 @@ dkstclose(Queue *q) return; } - /* - * decrement ref count on mux'd line - */ - streamexit(dp->s, 0); - /* * these states don't need the datakit */ @@ -534,14 +500,8 @@ out: if(lp->lineno == dp->ncsc) dp->csc = 0; - netdisown(&dp->net, lp->lineno); + netdisown(lp); lp->window = 0; - - lock(dp); - dp->ref--; - if(dp->ref == 0) - freeb(dp->alloc); - unlock(dp); } /* @@ -557,7 +517,8 @@ dkiput(Queue *q, Block *bp) * we assume that each put is a message. * * add a 2 byte channel number to the start of each message, - * low order byte first. + * low order byte first. Make sure the first block contains + * both the 2 channel bytes and the control byte. */ static void dkoput(Queue *q, Block *bp) @@ -706,9 +667,8 @@ void dkreset(void) { int i; - dk = (Dk*)xalloc(conf.dkif*sizeof(Dk)); - for(i = 0; i < conf.dkif; i++) - dk[i].prot = (Netprot*)xalloc(conf.nurp*sizeof(Netprot)); + + dk = (Dk*)xalloc(Maxdk*sizeof(Dk)); newqinfo(&dkmuxinfo); } @@ -759,7 +719,11 @@ dkstat(Chan *c, char *dp) Chan* dkopen(Chan *c, int omode) { - return netopen(c, omode, &dk[c->dev].net); + Dk *dp; + + dp = &dk[c->dev]; + linealloc(dp, STREAMID(c->qid.path), 1); + return netopen(c, omode, &dp->net); } void @@ -866,22 +830,21 @@ dkcloneline(Chan *c) /* * get an unused device and open its control file */ + qlock(&dp->netlock); for(line = dp->ncsc+1; line < dp->lines; line++){ lp = dp->linep[line]; - if(lp->state == Lclosed && canqlock(lp)){ - if(lp->state != Lclosed){ - qunlock(lp); - continue; - } + if(lp == 0 || lp->state == Lclosed){ + lp = linealloc(dp, line, 0); lp->state = Lopened; /* current user becomes owner */ - netown(&dp->net, lp->lineno, u->p->user, 0); + netown(lp, u->p->user, 0); - qunlock(lp); + qunlock(&dp->netlock); return lp->lineno; } } + qunlock(&dp->netlock); error(Enodev); return -1; /* never reached */ } @@ -911,12 +874,14 @@ dkopenline(Dk *dp, int line) static Chan* dkopencsc(Dk *dp) { - qlock(dp); + Line *lp; + + qlock(&dp->csclock); if(dp->csc == 0) dp->csc = dkopenline(dp, dp->ncsc); else incref(dp->csc); - qunlock(dp); + qunlock(&dp->csclock); return dp->csc; } @@ -999,7 +964,7 @@ dkcall(int type, Chan *c, char *addr, char *nuser, char *machine) line = STREAMID(c->qid.path); dp = &dk[c->dev]; - lp = dp->linep[line]; + lp = linealloc(dp, line, 1); /* * only dial on virgin lines @@ -1247,7 +1212,7 @@ dklisten(Chan *c) print("dklisten: illegal line %d\n", lineno); continue; } - lp = dp->linep[lineno]; + lp = linealloc(dp, lineno, 1); ts = strtoul(field[1], 0, 0); /* @@ -1321,7 +1286,7 @@ dklisten(Chan *c) lp->state = Lconnected; /* listener becomes owner */ - netown(&dp->net, lp->lineno, dp->prot[from].owner, 0); + netown(lp, dp->linep[from]->owner, 0); qunlock(lp); close(dc); @@ -1340,12 +1305,12 @@ static void dkanswer(Chan *c, int line, int code) { char reply[64]; - Dk *dp; Chan *dc; Line *lp; + Dk *dp; dp = &dk[c->dev]; - lp = dp->linep[line]; + lp = linealloc(dp, line, 1); /* * open the data file (c is a control file) @@ -1394,7 +1359,7 @@ dkwindow(Chan *c) long wins; Line *lp; - lp = dk[c->dev].linep[STREAMID(c->qid.path)]; + lp = linealloc(&dk[c->dev], STREAMID(c->qid.path), 1); if(lp->window == 0) lp->window = 64; sprint(buf, "init %d %d", lp->window, Streamhi); @@ -1488,12 +1453,11 @@ dkchgmesg(Chan *c, Dk *dp, Dkmsg *dialp, int line) switch (dialp->srv) { case D_CLOSE: /* remote shutdown */ - if (line <= 0 || line >= dp->lines) { + if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) { /* tell controller this line is not in use */ dkmesg(c, T_CHG, D_CLOSE, line, 0); return; } - lp = dp->linep[line]; switch (lp->state) { case Ldialing: @@ -1524,12 +1488,11 @@ dkchgmesg(Chan *c, Dk *dp, Dkmsg *dialp, int line) break; case D_ISCLOSED: /* acknowledging a local shutdown */ - if (line <= 0 || line >= dp->lines) { + if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) { /* tell controller this line is not in use */ dkmesg(c, T_CHG, D_CLOSE, line, 0); return; } - lp = dp->linep[line]; switch (lp->state) { case Llclose: case Lclosed: @@ -1550,6 +1513,8 @@ dkchgmesg(Chan *c, Dk *dp, Dkmsg *dialp, int line) */ for(line = dp->ncsc+1; line < dp->lines; line++){ lp = dp->linep[line]; + if(lp == 0) + continue; switch (lp->state) { case Ldialing: @@ -1595,10 +1560,9 @@ dkreplymesg(Dk *dp, Dkmsg *dialp, int line) DPRINT("dkreplymesg(%d)\n", line); - if(line < 0 || line >= dp->lines) + if(line < 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) return; - lp = dp->linep[line]; if(lp->state != Ldialing) return; @@ -1637,34 +1601,11 @@ dktimer(void *a) Chan *c; dp = (Dk *)a; - c = 0; - if(waserror()){ - /* - * hang up any calls waiting for the dk - */ - for (i=dp->ncsc+1; ilines; i++){ - lp = dp->linep[i]; - switch(lp->state){ - case Llclose: - lp->state = Lclosed; - break; - - case Ldialing: - dkreplymesg(dp, (Dkmsg *)0, i); - break; - } - } - if(c) - close(c); - return; - } - c = dkopencsc(dp); - for(;;){ - if(dp->opened==0) - error(Ehungup); + while(waserror()); + for(;;){ /* * send keep alive */ @@ -1677,6 +1618,8 @@ dktimer(void *a) */ for (i=dp->ncsc+1; ilines; i++){ lp = dp->linep[i]; + if(lp == 0) + continue; switch(lp->state){ case Llclose: dkmesg(c, T_CHG, D_CLOSE, i, 0); diff --git a/port/devenv.c b/port/devenv.c index ca50341c04e05f16d13dbe7d83ee7f08dffff249..9f21e238b6563a01e853e79bfb6bd68a8852645b 100644 --- a/port/devenv.c +++ b/port/devenv.c @@ -7,42 +7,14 @@ #include "devtab.h" -struct Envval +enum { - Envval *next; /* for hashing & easy deletion from hash list */ - Envval *prev; - ulong len; /* length of val that is valid */ - int ref; - char *val; + Maxenvsize = 16300, }; -enum{ - MAXENV = (BY2PG - sizeof(Envval)), - EVHASH = 64, - EVFREE = 16, - ALIGN = 16, -}; - -struct -{ - Envval *free[EVFREE+1]; - char *block; /* the free page we are allocating from */ - char *lim; /* end of block */ - int npage; /* total pages gotten from newpage() */ -}envalloc; - -QLock evlock; -Envval evhash[EVHASH]; -char *evscratch; /* for constructing the contents of a file */ - -Envval *newev(char*, ulong); -Envval *evalloc(ulong); -void evfree(Envval*); - void envreset(void) { - evscratch = xalloc(BY2PG); } void @@ -54,24 +26,22 @@ int envgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) { Egrp *eg; - Env *e; - int ans; + Evalue *e; eg = u->p->egrp; - qlock(&eg->ev); - if(s >= eg->nenv) - ans = -1; - else{ - e = &eg->etab[s]; - if(!e->name) - ans = 0; - else{ - devdir(c, (Qid){s+1, (ulong)e->name}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp); - ans = 1; - } + qlock(eg); + + for(e = eg->entries; e && s; e = e->link) + s--; + + if(e == 0) { + qunlock(eg); + return -1; } - qunlock(&eg->ev); - return ans; + + devdir(c, (Qid){e->path, 0}, e->name, e->len, eve, 0666, dp); + qunlock(eg); + return 1; } Chan* @@ -103,30 +73,31 @@ Chan * envopen(Chan *c, int omode) { Egrp *eg; - Env *e; - int mode; - - mode = openmode(omode); + Evalue *e; + + eg = u->p->egrp; if(c->qid.path & CHDIR){ if(omode != OREAD) error(Eperm); - }else{ - eg = u->p->egrp; - qlock(&eg->ev); - e = &eg->etab[c->qid.path-1]; - if(!e->name){ - qunlock(&eg->ev); + } + else { + qlock(eg); + for(e = eg->entries; e; e = e->link) + if(e->path == c->qid.path) + break; + + if(e == 0) { + qunlock(eg); error(Enonexist); } - if(omode == (OWRITE|OTRUNC) && e->val){ - qlock(&evlock); - evfree(e->val); - qunlock(&evlock); - e->val = 0; + if(omode == (OWRITE|OTRUNC) && e->value) { + free(e->value); + e->value = 0; + e->len = 0; } - qunlock(&eg->ev); + qunlock(eg); } - c->mode = mode; + c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; @@ -136,39 +107,36 @@ void envcreate(Chan *c, char *name, int omode, ulong perm) { Egrp *eg; - Env *e, *ne; - int i; + Evalue *e; if(c->qid.path != CHDIR) error(Eperm); + omode = openmode(omode); eg = u->p->egrp; - qlock(&eg->ev); - e = eg->etab; - ne = 0; - for(i = 0; i < eg->nenv; i++, e++) - if(e->name == 0) - ne = e; - else if(strcmp(e->name->val, name) == 0){ - qunlock(&eg->ev); - error(Einuse); - } - if(ne) - e = ne; - else if(eg->nenv == conf.npgenv){ - qunlock(&eg->ev); - print("out of egroup envs\n"); - error(Enoenv); + + qlock(eg); + if(waserror()) { + qunlock(eg); + nexterror(); } - i = e - eg->etab + 1; - e->val = 0; - qlock(&evlock); - e->name = newev(name, strlen(name)+1); - qunlock(&evlock); - if(i > eg->nenv) - eg->nenv = i; - qunlock(&eg->ev); - c->qid = (Qid){i, 0}; + + for(e = eg->entries; e; e = e->link) + if(strcmp(e->name, name) == 0) + error(Einuse); + + e = smalloc(sizeof(Evalue)); + e->name = smalloc(strlen(name)+1); + strcpy(e->name, name); + + e->path = ++eg->path; + e->link = eg->entries; + eg->entries = e; + c->qid = (Qid){e->path, 0}; + + qunlock(eg); + poperror(); + c->offset = 0; c->mode = omode; c->flag |= COPEN; @@ -178,19 +146,32 @@ void envremove(Chan *c) { Egrp *eg; - Env *e; + Evalue *e, **l; if(c->qid.path & CHDIR) error(Eperm); + eg = u->p->egrp; - qlock(&eg->ev); - e = &eg->etab[c->qid.path-1]; - if(!e->name){ - qunlock(&eg->ev); + qlock(eg); + + l = &eg->entries; + for(e = *l; e; e = e->link) { + if(e->path == c->qid.path) + break; + l = &e->link; + } + + if(e == 0) { + qunlock(eg); error(Enonexist); } - envpgclose(e); - qunlock(&eg->ev); + + *l = e->link; + qunlock(eg); + free(e->name); + if(e->value) + free(e->value); + free(e); } void @@ -206,206 +187,73 @@ envclose(Chan * c) USED(c); } -void -envpgcopy(Env *t, Env *f) -{ - qlock(&evlock); - if(t->name = f->name) - t->name->ref++; - if(t->val = f->val) - t->val->ref++; - qunlock(&evlock); -} - -void -envpgclose(Env *e) -{ - qlock(&evlock); - if(e->name) - evfree(e->name); - if(e->val) - evfree(e->val); - e->name = e->val = 0; - qunlock(&evlock); -} - long envread(Chan *c, void *a, long n, ulong offset) { Egrp *eg; - Env *e; - Envval *ev; - long vn; + Evalue *e; if(c->qid.path & CHDIR) return devdirread(c, a, n, 0, 0, envgen); + eg = u->p->egrp; - qlock(&eg->ev); - e = &eg->etab[c->qid.path-1]; - if(!e->name){ - qunlock(&eg->ev); + qlock(eg); + for(e = eg->entries; e; e = e->link) + if(e->path == c->qid.path) + break; + + if(e == 0) { + qunlock(eg); error(Enonexist); } - ev = e->val; - vn = ev ? ev->len : 0; - if(offset + n > vn) - n = vn - offset; + + if(offset + n > e->len) + n = e->len - offset; if(n <= 0) n = 0; else - memmove(a, ev->val + offset, n); - qunlock(&eg->ev); + memmove(a, e->value+offset, n); + qunlock(eg); return n; } long envwrite(Chan *c, void *a, long n, ulong offset) { + char *s; + int vend; Egrp *eg; - Env *e; - Envval *ev; - ulong olen; + Evalue *e; if(n <= 0) return 0; - olen = (offset + n + ALIGN - 1) & ~(ALIGN - 1); - if(olen > MAXENV) + + vend = offset+n; + if(vend > Maxenvsize) error(Etoobig); - eg = u->p->egrp; - qlock(&eg->ev); - e = &eg->etab[c->qid.path-1]; - if(!e->name){ - qunlock(&eg->ev); - error(Enonexist); - } - ev = e->val; - olen = ev ? ev->len : 0; - qlock(&evlock); - if(offset == 0 && n >= olen) - e->val = newev(a, n); - else{ - if(olen > offset) - olen = offset; - if(ev) - memmove(evscratch, ev->val, olen); - if(olen < offset) - memset(evscratch + olen, '\0', offset - olen); - memmove(evscratch + offset, a, n); - e->val = newev(evscratch, offset + n); - } - if(ev) - evfree(ev); - qunlock(&evlock); - qunlock(&eg->ev); - return n; -} -/* - * called with evlock qlocked - */ -Envval * -newev(char *s, ulong n) -{ - Envval *ev; - uchar *t; - int h; - - h = 0; - for(t = (uchar*)s; t - (uchar*)s < n; t++) - h = (h << 1) ^ *t; - h &= EVHASH - 1; - for(ev = evhash[h].next; ev; ev = ev->next) - if(ev->len == n && memcmp(ev->val, s, n) == 0){ - ev->ref++; - return ev; - } - ev = evalloc(n); - ev->len = n; - memmove(ev->val, s, n); - if(ev->next = evhash[h].next) - ev->next->prev = ev; - evhash[h].next = ev; - ev->prev = &evhash[h]; - return ev; -} + eg = u->p->egrp; + qlock(eg); + for(e = eg->entries; e; e = e->link) + if(e->path == c->qid.path) + break; -/* - * called only from newev - */ -Envval * -evalloc(ulong n) -{ - Envval *ev, **p; - char *b, *lim; - ulong size; - - size = (n + ALIGN - 1) & ~(ALIGN - 1); - n = (size - 1) / ALIGN; - p = &envalloc.free[n < EVFREE ? n : EVFREE]; - for(ev = *p; ev; ev = *p){ - if(ev->len == size){ - *p = ev->next; - ev->ref = 1; - return ev; - } - p = &ev->next; + if(e == 0) { + qunlock(eg); + error(Enonexist); } - /* - * make sure we have enough space to allocate the buffer. - * if not, use the remaining space for the smallest buffers - */ - if(size > MAXENV) - panic("evalloc"); - b = envalloc.block; - lim = envalloc.lim; - if(!b || lim < b + size + sizeof *ev){ - p = &envalloc.free[0]; - while(lim >= b + ALIGN + sizeof *ev){ - ev = (Envval*)b; - ev->len = ALIGN; - ev->val = b + sizeof *ev; - ev->next = *p; - *p = ev; - b += ALIGN + sizeof *ev; - } - b = (char*)VA(kmap(newpage(0, 0, 0))); - envalloc.npage++; - envalloc.lim = b + BY2PG; + if(vend > e->len) { + s = smalloc(offset+n); + memmove(s, e->value, e->len); + if(e->value) + free(e->value); + e->value = s; + e->len = vend; } - - ev = (Envval*)b; - ev->val = b + sizeof *ev; - ev->ref = 1; - envalloc.block = b + size + sizeof *ev; - return ev; -} - -/* - * called with evlock qlocked - */ -void -evfree(Envval *ev) -{ - int n; - - if(--ev->ref > 0) - return; - - if(ev->prev) - ev->prev->next = ev->next; - else - panic("evfree"); - if(ev->next) - ev->next->prev = ev->prev; - n = (ev->len + ALIGN - 1) & ~(ALIGN - 1); - ev->len = n; - n = (n - 1) / ALIGN; - if(n > EVFREE) - n = EVFREE; - ev->next = envalloc.free[n]; - ev->prev = 0; - envalloc.free[n] = ev; + memmove(e->value+offset, a, n); + qunlock(eg); + return n; } /* diff --git a/port/devip.c b/port/devip.c index 05787c42395b293df12aeca13ba89414dde51003..13a14675ee2a8d83ce7315f4ad02a375ce8078fe 100644 --- a/port/devip.c +++ b/port/devip.c @@ -57,9 +57,9 @@ ipinitnet(Network *np, Qinfo *stproto, Ipconv *cp) int j; for(j = 0; j < conf.ip; j++, cp++){ - cp->index = j; cp->stproto = stproto; cp->net = np; + netadd(np, cp, j); } np->name = stproto->name; np->nconv = conf.ip; @@ -68,7 +68,6 @@ ipinitnet(Network *np, Qinfo *stproto, Ipconv *cp) if(stproto != &udpinfo) np->listen = iplisten; np->clone = ipclonecon; - np->prot = (Netprot *)xalloc(sizeof(Netprot) * conf.ip); np->ninfo = 3; np->info[0].name = "remote"; np->info[0].fill = ipremotefill; @@ -172,10 +171,9 @@ ipincoming(Ipconv *base, Ipconv *from) continue; } if(from) /* copy ownership from listening channel */ - netown(new->net, new->index, - new->net->prot[from->index].owner, 0); + netown(new, from->owner, 0); else /* current user becomes owner */ - netown(new->net, new->index, u->p->user, 0); + netown(new, u->p->user, 0); new->ref = 1; qunlock(new); diff --git a/port/devlance.c b/port/devlance.c index 627174a8800f56f855d13f4f8341b2c793846ea8..e37444e9b46488ca40a82e1a6df883256ee5d7a2 100644 --- a/port/devlance.c +++ b/port/devlance.c @@ -76,6 +76,7 @@ typedef struct Ethertype Ethertype; struct Ethertype { QLock; + Netprot; /* stat info */ int type; /* ethernet type */ int prom; /* promiscuous mode */ Queue *q; @@ -96,7 +97,6 @@ typedef struct { int all; /* number of channels listening to all packets */ int wedged; /* the lance is wedged */ Network net; - Netprot prot[Ntypes]; int inited; uchar *lmp; /* location of parity test */ @@ -268,7 +268,7 @@ lancestclose(Queue *q) et->q = 0; et->prom = 0; et->inuse = 0; - netdisown(&l.net, et - l.e); + netdisown(et); } /* @@ -416,6 +416,7 @@ void lancereset(void) { static int already; + int i; if(already == 0){ already = 1; @@ -428,11 +429,12 @@ lancereset(void) l.net.listen = 0; l.net.clone = lanceclonecon; l.net.ninfo = 2; - l.net.prot = l.prot; l.net.info[0].name = "stats"; l.net.info[0].fill = lancestatsfill; l.net.info[1].name = "type"; l.net.info[1].fill = lancetypefill; + for(i = 0; i < Ntypes; i++) + netadd(&l.net, &l.e[i], i); memset(l.bcast, 0xff, sizeof l.bcast); } @@ -671,7 +673,7 @@ lanceclonecon(Chan *c) continue; } e->inuse = 1; - netown(&l.net, e - l.e, u->p->user, 0); + netown(e, u->p->user, 0); qunlock(e); return e - l.e; } diff --git a/port/devpipe.c b/port/devpipe.c index 2bb9f71b772f4afd3efbc7a1f9691f486ce25bf1..34602a64dfbbe85af66d1f0d15d89e0a9cd3e9fb 100644 --- a/port/devpipe.c +++ b/port/devpipe.c @@ -161,9 +161,7 @@ pipeopen(Chan *c, int omode) remote->devq->ptr = local; local->devq->other->next = remote->devq; remote->devq->other->next = local->devq; - } - else - if(local->opens == 1){ + } else if(local->opens == 1){ /* * keep other side around till last close of this side */ @@ -321,6 +319,6 @@ getpipe(ulong path) } } unlock(&pipealloc); - panic("getpipe"); + error(Enonexist); return 0; } diff --git a/port/devscc.c b/port/devscc.c index d1ad779d7772a1b05d38f834ebc7f8347808b892..31fca51bc1b877e8561a1f05a8152f38273928a0 100644 --- a/port/devscc.c +++ b/port/devscc.c @@ -754,7 +754,7 @@ sccread(Chan *c, void *buf, long n, ulong offset) return streamread(c, buf, n); case Sctlqid: sprint(b, "%d", STREAMID(c->qid.path)); - return stringread(buf, n, b, offset); + return readstr(offset, buf, n, b); } error(Egreg); return 0; /* not reached */ diff --git a/port/ipdat.h b/port/ipdat.h index 5ccfb80f70c38e410e81119bc3c11b7ff2a8fb5d..50ebf5e06a3602c070c74d5eea813c02ab61e42e 100644 --- a/port/ipdat.h +++ b/port/ipdat.h @@ -278,8 +278,8 @@ struct Reseq struct Ipconv { QLock; /* Ref count lock */ + Netprot; /* stat info */ int ref; - int index; Qinfo *stproto; /* Stream protocol for this device */ Network *net; /* user level network interface */ Ipaddr dst; /* Destination from connect */ diff --git a/port/net.c b/port/net.c index 393e50d48b4a2b3504551d146b25daf79d82196c..306dffcb02b0b8574d869f55ffebae23e9d6758c 100644 --- a/port/net.c +++ b/port/net.c @@ -14,6 +14,20 @@ enum Qinf= 5, }; +/* + * find protection structure + */ +static Netprot* +findprot(Network *np, int id) +{ + Netprot *p; + + for(p = np->prot; p; p = p->next) + if(p->id == id) + break; + return p; +} + /* * generate a 3 level directory */ @@ -24,7 +38,6 @@ netgen(Chan *c, void *vp, int ntab, int i, Dir *dp) char buf[32]; Network *np = vp; int t; - int id; Netprot *p; int perm; char *o; @@ -61,9 +74,8 @@ netgen(Chan *c, void *vp, int ntab, int i, Dir *dp) } /* third level depends on the number of info files */ - id = STREAMID(c->qid.path); - p = &np->prot[id]; - if(*p->owner){ + p = findprot(np, STREAMID(c->qid.path)); + if(p && *p->owner){ o = p->owner; perm = p->mode; } else { @@ -153,7 +165,9 @@ netwstat(Chan *c, char *db, Network *np) Dir dir; Netprot *p; - p = &np->prot[STREAMID(c->qid.path)]; + p = findprot(np, STREAMID(c->qid.path)); + if(p == 0) + error(Enonexist); lock(np); if(strncmp(p->owner, u->p->user, NAMELEN)){ unlock(np); @@ -169,6 +183,7 @@ Chan * netopen(Chan *c, int omode, Network *np) { int id = 0; + Netprot *p; if(c->qid.path & CHDIR){ if(omode != OREAD) @@ -199,7 +214,9 @@ netopen(Chan *c, int omode, Network *np) streamopen(c, np->devp); if(np->protop && c->stream->devq->next->info != np->protop) pushq(c->stream, np->protop); - if(netown(np, id, u->p->user, omode&7) < 0) + p = findprot(np, id); +if(p == 0) print("netopen: can't find %d\n", id); + if(netown(p, u->p->user, omode&7) < 0) error(Eperm); break; } @@ -227,19 +244,36 @@ netread(Chan *c, void *a, long n, ulong offset, Network *np) error(Ebadusefd); (*np->info[t-Qinf].fill)(c, buf, sizeof(buf)); - return stringread(a, n, buf, offset); + return readstr(offset, a, n, buf); } +void +netadd(Network *np, Netprot *p, int id) +{ + Netprot **l, *pp; + + memset(p, 0, sizeof(Netprot)); + p->id = id; + + l = &np->prot; + for(pp = np->prot; pp; pp = pp->next){ + if(pp->id == id) + panic("netadd"); + l = &pp->next; + } + *l = p; +} + +Lock netlock; + int -netown(Network *np, int id, char *o, int omode) +netown(Netprot *p, char *o, int omode) { static int access[] = { 0400, 0200, 0600, 0100 }; - Netprot *p; int mode; int t; - p = &np->prot[id]; - lock(np); + lock(&netlock); if(*p->owner){ if(strncmp(o, p->owner, NAMELEN) == 0) /* User */ mode = p->mode; @@ -250,22 +284,21 @@ netown(Network *np, int id, char *o, int omode) t = access[omode&3]; if((t & mode) == t){ - unlock(np); + unlock(&netlock); return 0; } else { - unlock(np); + unlock(&netlock); return -1; } } strncpy(p->owner, o, NAMELEN); - np->prot[id].mode = 0660; - unlock(np); + p->mode = 0660; + unlock(&netlock); return 0; } void -netdisown(Network *np, int id) +netdisown(Netprot *p) { -if(np == 0) panic("np == 0"); - *np->prot[id].owner = 0; + p->owner[0] = 0; } diff --git a/port/pgrp.c b/port/pgrp.c index 435e2f0c6734a37e841bb8a87da26d4107077127..b5dba70012b76c9f978126bbc62073ecc151633c 100644 --- a/port/pgrp.c +++ b/port/pgrp.c @@ -52,29 +52,6 @@ newpgrp(void) return p; } -Egrp* -newegrp(void) -{ - Egrp *e; - - e = smalloc(sizeof(Egrp)+sizeof(Env)*conf.npgenv); - - /* This is a sleazy hack to make malloc work .. devenv need rewriting. */ - e->etab = (Env*)((uchar*)e+sizeof(Egrp)); - e->ref = 1; - return e; -} - -Fgrp* -newfgrp(void) -{ - Fgrp *f; - - f = smalloc(sizeof(Fgrp)); - f->ref = 1; - return f; -} - Fgrp* dupfgrp(Fgrp *f) { @@ -82,7 +59,8 @@ dupfgrp(Fgrp *f) Chan *c; int i; - new = newfgrp(); + new = smalloc(sizeof(Fgrp)); + new->ref = 1; lock(f); new->maxfd = f->maxfd; @@ -139,14 +117,16 @@ closepgrp(Pgrp *p) void closeegrp(Egrp *eg) { - Env *e; - int i; + Evalue *e, *next; if(decref(eg) == 0) { - e = eg->etab; - for(i=0; inenv; i++, e++) - envpgclose(e); - + for(e = eg->entries; e; e = next) { + next = e->link; + free(e->name); + if(e->value) + free(e->value); + free(e); + } free(eg); } } @@ -183,17 +163,24 @@ newmount(Mhead *mh, Chan *to) void envcpy(Egrp *to, Egrp *from) { - Env *te, *fe; - int i, nenv; - - qlock(&from->ev); - nenv = from->nenv; - to->nenv = nenv; - te = to->etab; - fe = from->etab; - for(i=0; i < nenv; i++, te++, fe++) - envpgcopy(te, fe); - qunlock(&from->ev); + Evalue **l, *ne, *e; + + l = &to->entries; + qlock(from); + for(e = from->entries; e; e = e->link) { + ne = smalloc(sizeof(Evalue)); + ne->name = smalloc(strlen(e->name)+1); + strcpy(ne->name, e->name); + if(e->value) { + ne->value = smalloc(e->len); + memmove(ne->value, e->value, e->len); + ne->len = e->len; + } + ne->path = ++to->path; + *l = ne; + l = &ne->link; + } + qunlock(from); } void diff --git a/port/portdat.h b/port/portdat.h index e6a3f4cccb215aadad9f93d58f750dc0cc331a70..78e26b448f5586d39577ac5289d795f276b7dd57 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -6,8 +6,7 @@ typedef struct Crypt Crypt; typedef struct Dev Dev; typedef struct Dirtab Dirtab; typedef struct Egrp Egrp; -typedef struct Env Env; -typedef struct Envval Envval; +typedef struct Evalue Evalue; typedef struct Etherpkt Etherpkt; typedef struct Fgrp Fgrp; typedef struct Image Image; @@ -192,12 +191,6 @@ struct Dirtab long perm; }; -struct Env -{ - Envval *name; - Envval *val; -}; - /* * Ethernet packet buffers. */ @@ -394,9 +387,18 @@ struct Pgrp struct Egrp { Ref; - int nenv; /* highest active env table entry, +1 */ - QLock ev; /* for all of etab */ - Env *etab; + QLock; + Evalue *entries; + ulong path; +}; + +struct Evalue +{ + char *name; + char *value; + int len; + ulong path; + Evalue *link; }; #define NFD 100 @@ -651,6 +653,8 @@ enum */ struct Netprot { + int id; + Netprot *next; /* linked list of protections */ ulong mode; char owner[NAMELEN]; }; @@ -672,7 +676,7 @@ struct Network int (*clone)(Chan*); int ninfo; Netinf info[5]; - Netprot *prot; /* protections */ + Netprot *prot; /* linked list of protections */ }; #define MAJOR(q) ((q) >> 8) #define MINOR(q) ((q) & 0xff) diff --git a/port/portfns.h b/port/portfns.h index 513c2abab574844cb7d24f9f4617374ef2c22939..7e2ca623f8bc53c2cacf2ef1f0da42541e874f84 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -28,7 +28,6 @@ void confinit1(int); int consactive(void); void consdebug(void); Block* copyb(Block*, int); -Env* copyenv(Env*, int); void copypage(Page*, Page*); int decref(Ref*); int decrypt(void*, void*, int); @@ -50,8 +49,6 @@ void duppage(Page*); void dupswap(Page*); int encrypt(void*, void*, int); void envcpy(Egrp*, Egrp*); -void envpgclose(Env*); -void envpgcopy(Env*, Env*); int eqchan(Chan*, Chan*, long); int eqqid(Qid, Qid); void error(char*); @@ -114,19 +111,19 @@ int mount(Chan*, Chan*, int); void mountfree(Mount*); void mouseclock(void); int mouseputc(IOQ*, int); +int msize(void*); Chan* namec(char*, int, int, ulong); void nameok(char*); -void netdisown(Network*, int); +void netdisown(Netprot*); int netgen(Chan*, void*, int, int, Dir*); Chan* netopen(Chan*, int, Network*); -int netown(Network*, int, char*, int); +int netown(Netprot*, char*, int); +void netadd(Network*, Netprot*, int); long netread(Chan*, void*, long, ulong, Network*); void netstat(Chan*, char*, Network*); int netwalk(Chan*, char*, Network*); void netwstat(Chan*, char*, Network*); Chan* newchan(void); -Egrp* newegrp(void); -Fgrp* newfgrp(void); Mount* newmount(Mhead*, Chan*); Page* newpage(int, Segment **, ulong); Pgrp* newpgrp(void); @@ -180,6 +177,7 @@ Qinfo* qinfofind(char*); void qlock(QLock*); void qunlock(QLock*); int readnum(ulong, char*, ulong, ulong, int); +int readstr(ulong, char*, ulong, char*); void ready(Proc*); void relocateseg(Segment*, ulong); void resched(char*); @@ -213,7 +211,7 @@ void splx(int); int streamclose(Chan*); int streamclose1(Stream*); int streamenter(Stream*); -int streamexit(Stream*, int); +void streamexit(Stream*, int); Devgen streamgen; void streaminit(void); void streaminit0(void); diff --git a/port/stasync.c b/port/stasync.c index 70e0dd01938a214a760ad6bf30ceb0e1fc794b02..8c638c0cc41480f79ce596683bfae9c215136643 100644 --- a/port/stasync.c +++ b/port/stasync.c @@ -24,8 +24,12 @@ enum Escape }; -typedef struct Async { +typedef struct Async Async; +struct Async +{ QLock; + Async *list; + int id; int inuse; Queue *wq; @@ -51,9 +55,16 @@ typedef struct Async { ulong badescape; ulong in; /* bytes in */ ulong out; /* bytes out */ -} Async; +}; + +int nasync; -Async *async; +/* list of allocated async structures (never freed) */ +struct +{ + Lock; + Async *async; +} asyncalloc; /* * async stream module definition @@ -97,7 +108,6 @@ static ushort crc_table[256] = { static void asyncreset(void) { - async = (Async *)xalloc(conf.nasync*sizeof(Async)); } /* @@ -110,14 +120,21 @@ asyncopen(Queue *q, Stream *s) DPRINT("asyncopen %d\n", s->dev); - for(ap = async; ap < &async[conf.nasync]; ap++){ + for(ap = asyncalloc.async; ap; ap = ap->list){ qlock(ap); if(ap->inuse == 0) break; qunlock(ap); } - if(ap == &async[conf.nasync]) - exhausted("async stream modules"); + if(ap == 0){ + ap = smalloc(sizeof(Async)); + qlock(ap); + lock(&asyncalloc); + ap->list = asyncalloc.async; + asyncalloc.async = ap; + ap->id = nasync++; + unlock(&asyncalloc); + } q->ptr = q->other->ptr = ap; ap->inuse = 1; @@ -141,7 +158,7 @@ asyncclose(Queue * q) { Async *ap = (Async *)q->ptr; - DPRINT("asyncstclose %d\n", ap-async); + DPRINT("asyncstclose %d\n", ap->id); qlock(ap); ap->inuse = 0; qunlock(ap); @@ -166,7 +183,7 @@ freemsg(Queue *q, Block *bp) static void showframe(char *t, Async *ap, uchar *buf, int n) { - kprint("a%d %s [", ap-async, t); + kprint("a%d %s [", ap->id, t); while (--n >= 0) kprint(" %2.2ux", *buf++); kprint(" ]\n"); @@ -284,7 +301,7 @@ asyncoput(Queue *q, Block *bp) if(asyncdebug > 1) kprint("a%d->(%d)%3.3uo %d\n", - ap-async, chan, ctl, bp->wptr-bp->rptr); + ap->id, chan, ctl, bp->wptr-bp->rptr); /* * send the 8 bit data @@ -336,7 +353,7 @@ asdeliver(Queue *q, Async *ap) chan = *p++ & 0x7e; chan = (chan<<5)|((*p++ & 0x7e)>>1); if(chan==0) { - DPRINT("a%d deliver chan 0\n", ap-async); + DPRINT("a%d deliver chan 0\n", ap->id); ap->chan0++; return; } @@ -355,7 +372,7 @@ asdeliver(Queue *q, Async *ap) bp->rptr[2] = c; if(asyncdebug > 1) kprint("a%d<-(%d)%3.3uo %d\n", - ap-async, chan, bp->rptr[2], + ap->id, chan, bp->rptr[2], bp->wptr - bp->rptr - 3); PUTNEXT(q, bp); bp = 0; @@ -368,7 +385,7 @@ asdeliver(Queue *q, Async *ap) if(bp) { if(asyncdebug > 1) kprint("a%d<-(%d)%3.3uo %d\n", - ap-async, chan, bp->rptr[2], + ap->id, chan, bp->rptr[2], bp->wptr - bp->rptr - 3); PUTNEXT(q, bp); } @@ -411,7 +428,7 @@ asynciput(Queue *q, Block *bp) } Datachar: if(ap->icount >= MAXFRAME) { - DPRINT("a%d pkt too long\n", ap-async); + DPRINT("a%d pkt too long\n", ap->id); ap->toolong++; state = Hunt; break; @@ -426,12 +443,12 @@ asynciput(Queue *q, Block *bp) if(asyncdebug > 2) showframe("in", ap, ap->buf, ap->icount); if(ap->icount < 5) { - DPRINT("a%d pkt too short\n", ap-async); + DPRINT("a%d pkt too short\n", ap->id); if(asyncdebug && asyncdebug<=2) showframe("shortin", ap, ap->buf, ap->icount); ap->tooshort++; } else if(ap->icrc != 0) { - DPRINT("a%d bad crc\n", ap-async); + DPRINT("a%d bad crc\n", ap->id); if(asyncdebug && asyncdebug<=2) showframe("badin", ap, ap->buf, ap->icount); ap->badcrc++; @@ -445,7 +462,7 @@ asynciput(Queue *q, Block *bp) state = Data; goto Datachar; default: - DPRINT("a%d bad escape\n", ap-async); + DPRINT("a%d bad escape\n", ap->id); ap->badescape++; state = Hunt; break; diff --git a/port/stip.c b/port/stip.c index ee4425df7790048bb54aad8a85e84ee17433a2bb..25ba8089733fd455f7d5c1c3d808523586248dea 100644 --- a/port/stip.c +++ b/port/stip.c @@ -145,7 +145,7 @@ ipetherclose(Queue *q) ipc = (Ipconv *)(q->ptr); if(ipc){ - netdisown(ipc->net, ipc->index); + netdisown(ipc); ipc->ref = 0; } } diff --git a/port/stream.c b/port/stream.c index b0578f243b9291dda9d8e6c520687626bf794055..701ff9a7e16cea4cc5109b1416dbc890c5a7427f 100644 --- a/port/stream.c +++ b/port/stream.c @@ -7,85 +7,28 @@ #include "../port/error.h" #include "devtab.h" -enum { - Nclass=4, /* number of block classes */ -}; - -/* - * process end line discipline - */ -static void stputq(Queue*, Block*); -Qinfo procinfo = -{ - stputq, - nullput, - 0, - 0, - "process" -}; - -/* - * line disciplines that can be pushed - */ -static Qinfo *lds; - -Stream *slist; -Queue *qlist; -static Lock garbagelock; - -/* - * Allocate streams, queues, and blocks. Allocate n block classes with - * 1/2(m+1) to class m < n-1 - * 1/2(n-1) to class n-1 - */ -void -streaminit(void) -{ - - /* - * allocate queues, streams - */ - slist = (Stream *)xalloc(conf.nstream * sizeof(Stream)); - qlist = (Queue *)xalloc(conf.nqueue * sizeof(Queue)); - - /* - * make stream modules available - */ - streaminit0(); -} - /* - * make known a stream module and call its initialization routine, if - * it has one. + * Part 1) Blocks */ -void -newqinfo(Qinfo *qi) -{ - if(qi->next) - panic("newqinfo: already configured"); - - qi->next = lds; - lds = qi; - if(qi->reset) - (*qi->reset)(); -} /* - * allocate a block + * Allocate a block. Put the data portion at the end of the smalloc'd + * chunk so that it can easily grow from the front to add protocol + * headers. Thank Larry Peterson for the suggestion. */ Block * allocb(ulong size) { Block *bp; - uchar *data; + uchar *base, *lim; bp = smalloc(sizeof(Block)+size); - data = (uchar*)bp + sizeof(Block); - bp->rptr = data; - bp->wptr = data; - bp->base = data; - bp->lim = data+size; + base = (uchar*)bp + sizeof(Block); + lim = (uchar*)bp + msize(bp); + bp->wptr = bp->rptr = lim - size; + bp->base = base; + bp->lim = lim; bp->flags = 0; bp->next = 0; bp->list = 0; @@ -95,7 +38,7 @@ allocb(ulong size) /* * Free a block (or list of blocks). Poison its pointers so that - * someone trying to access it after freeing will cause a dump. + * someone trying to access it after freeing will cause a panic. */ void freeb(Block *bp) @@ -112,7 +55,8 @@ freeb(Block *bp) } /* - * pad a block to the front with n bytes + * Pad a block to the front with n bytes. This is used to add protocol + * headers to the front of blocks. */ Block * padb(Block *bp, int n) @@ -131,6 +75,253 @@ padb(Block *bp, int n) } } +/* + * make sure the first block has n bytes + */ +Block * +pullup(Block *bp, int n) +{ + Block *nbp; + int i; + + /* + * this should almost always be true, the rest it + * just for to avoid every caller checking. + */ + if(BLEN(bp) >= n) + return bp; + + /* + * if not enough room in the first block, + * add another to the front of the list. + */ + if(bp->lim - bp->rptr < n){ + nbp = allocb(n); + nbp->next = bp; + bp = nbp; + } + + /* + * copy bytes from the trailing blocks into the first + */ + n -= BLEN(bp); + while(nbp = bp->next){ + i = BLEN(nbp); + if(i >= n) { + memmove(bp->wptr, nbp->rptr, n); + bp->wptr += n; + nbp->rptr += n; + return bp; + } else { + memmove(bp->wptr, nbp->rptr, i); + bp->wptr += i; + bp->next = nbp->next; + nbp->next = 0; + freeb(nbp); + n -= i; + } + } + freeb(bp); + return 0; +} + +/* + * return the number of data bytes of a list of blocks + */ +int +blen(Block *bp) +{ + int len; + + len = 0; + while(bp) { + len += BLEN(bp); + bp = bp->next; + } + + return len; +} + +/* + * round a block chain to some even number of bytes. Used + * by devip.c becuase all IP packets must have an even number + * of bytes. + * + * The last block in the returned chain will have S_DELIM set. + */ +int +bround(Block *bp, int amount) +{ + Block *last; + int len, pad; + + len = 0; + SET(last); /* Ken's magic */ + + while(bp) { + len += BLEN(bp); + last = bp; + bp = bp->next; + } + + pad = ((len + amount) & ~amount) - len; + if(pad) { + if(last->lim - last->wptr >= pad){ + memset(last->wptr, 0, pad); + last->wptr += pad; + } else { + last->next = allocb(pad); + last->flags &= ~S_DELIM; + last = last->next; + last->wptr += pad; + last->flags |= S_DELIM; + } + } + + return len + pad; +} + +/* + * expand a block list to be one block, len bytes long. used by + * ethernet routines. + */ +Block* +expandb(Block *bp, int len) +{ + Block *nbp, *new; + int i; + ulong delim = 0; + + new = allocb(len); + if(new == 0){ + freeb(bp); + return 0; + } + + /* + * copy bytes into new block + */ + for(nbp = bp; len>0 && nbp; nbp = nbp->next){ + delim = nbp->flags & S_DELIM; + i = BLEN(nbp); + if(i > len) { + memmove(new->wptr, nbp->rptr, len); + new->wptr += len; + break; + } else { + memmove(new->wptr, nbp->rptr, i); + new->wptr += i; + len -= i; + } + } + if(len){ + memset(new->wptr, 0, len); + new->wptr += len; + } + new->flags |= delim; + freeb(bp); + return new; + +} + +/* + * make a copy of the first 'count' bytes of a block chain. Use + * by transport protocols. + */ +Block * +copyb(Block *bp, int count) +{ + Block *nb, *head, **p; + int l; + + p = &head; + while(count) { + l = BLEN(bp); + if(count < l) + l = count; + nb = allocb(l); + if(nb == 0) + panic("copyb.1"); + memmove(nb->wptr, bp->rptr, l); + nb->wptr += l; + count -= l; + if(bp->flags & S_DELIM) + nb->flags |= S_DELIM; + *p = nb; + p = &nb->next; + bp = bp->next; + if(bp == 0) + break; + } + if(count) { + nb = allocb(count); + if(nb == 0) + panic("copyb.2"); + memset(nb->wptr, 0, count); + nb->wptr += count; + nb->flags |= S_DELIM; + *p = nb; + } + if(blen(head) == 0) + print("copyb: zero length\n"); + + return head; +} + +/* + * Part 2) Queues + */ + +/* + * process end line discipline + */ +static void stputq(Queue*, Block*); +Qinfo procinfo = +{ + stputq, + nullput, + 0, + 0, + "process" +}; + +/* + * line disciplines that can be pushed + */ +static Qinfo *lds; + +/* + * make known a stream module and call its initialization routine, if + * it has one. + */ +void +newqinfo(Qinfo *qi) +{ + if(qi->next) + panic("newqinfo: already configured"); + + qi->next = lds; + lds = qi; + if(qi->reset) + (*qi->reset)(); +} + +/* + * find the info structure for line discipline 'name' + */ +Qinfo * +qinfofind(char *name) +{ + Qinfo *qi; + + if(name == 0) + return 0; + for(qi = lds; qi; qi = qi->next) + if(strcmp(qi->name, name)==0) + return qi; + return 0; +} + /* * allocate a pair of queues. flavor them with the requested put routines. * the `QINUSE' flag on the read side is the only one used. @@ -140,20 +331,7 @@ allocq(Qinfo *qi) { Queue *q, *wq; - for(q=qlist; q<&qlist[conf.nqueue]; q++, q++) { - if(q->flag == 0){ - if(canlock(q)){ - if(q->flag == 0) - break; - unlock(q); - } - } - } - - if(q == &qlist[conf.nqueue]){ - print("no more queues\n"); - exhausted("queues"); - } + q = smalloc(2*sizeof(Queue)); q->flag = QINUSE; q->r.p = 0; @@ -173,16 +351,14 @@ allocq(Qinfo *qi) wq->len = wq->nb = 0; wq->rp = &wq->r; - unlock(q); - return q; } /* - * flush a queue + * free a queue */ static void -flushq(Queue *q) +freeq(Queue *q) { Block *bp; @@ -192,13 +368,14 @@ flushq(Queue *q) q = WR(q); while(bp = getq(q)) freeb(bp); + free(RD(q)); } /* - * free a queue + * flush a queue */ static void -freeq(Queue *q) +flushq(Queue *q) { Block *bp; @@ -208,7 +385,6 @@ freeq(Queue *q) q = WR(q); while(bp = getq(q)) freeb(bp); - RD(q)->flag = 0; } /* @@ -297,52 +473,6 @@ putq(Queue *q, Block *bp) return delim; } -int -blen(Block *bp) -{ - int len; - - len = 0; - while(bp) { - len += BLEN(bp); - bp = bp->next; - } - - return len; -} - -/* - * bround - round a block chain to some 2^n number of bytes - */ -int -bround(Block *bp, int amount) -{ - Block *last; - int len, pad; - - len = 0; - SET(last); /* Ken's magic */ - - while(bp) { - len += BLEN(bp); - last = bp; - bp = bp->next; - } - - pad = ((len + amount) & ~amount) - len; - if(pad) { - last->next = allocb(pad); - last->flags &= ~S_DELIM; - last = last->next; - memset(last->wptr, 0, pad); - last->wptr += pad; - last->flags |= S_DELIM; - - } - - return len + pad; -} - int putb(Blist *q, Block *bp) { @@ -440,209 +570,35 @@ getb(Blist *q) bp = q->first; if(bp) { - q->first = bp->next; - if(q->first == 0) - q->last = 0; - q->len -= BLEN(bp); - bp->next = 0; - } - return bp; -} - -/* - * make sure the first block has n bytes - */ -Block * -pullup(Block *bp, int n) -{ - Block *nbp; - int i; - - /* - * this should almost always be true, the rest it - * just for to avoid every caller checking. - */ - if(BLEN(bp) >= n) - return bp; - - /* - * if not enough room in the first block, - * add another to the front of the list. - */ - if(bp->lim - bp->rptr < n){ - nbp = allocb(n); - nbp->next = bp; - bp = nbp; - } - - /* - * copy bytes from the trailing blocks into the first - */ - n -= BLEN(bp); - while(nbp = bp->next){ - i = BLEN(nbp); - if(i >= n) { - memmove(bp->wptr, nbp->rptr, n); - bp->wptr += n; - nbp->rptr += n; - return bp; - } else { - memmove(bp->wptr, nbp->rptr, i); - bp->wptr += i; - bp->next = nbp->next; - nbp->next = 0; - freeb(nbp); - } - } - freeb(bp); - return 0; -} - -/* - * expand a block list to be one block, len bytes long - */ -Block* -expandb(Block *bp, int len) -{ - Block *nbp, *new; - int i; - ulong delim = 0; - - new = allocb(len); - if(new == 0){ - freeb(bp); - return 0; - } - - /* - * copy bytes into new block - */ - for(nbp = bp; len>0 && nbp; nbp = nbp->next){ - delim = nbp->flags & S_DELIM; - i = BLEN(nbp); - if(i > len) { - memmove(new->wptr, nbp->rptr, len); - new->wptr += len; - break; - } else { - memmove(new->wptr, nbp->rptr, i); - new->wptr += i; - len -= i; - } - } - if(len){ - memset(new->wptr, 0, len); - new->wptr += len; - } - new->flags |= delim; - freeb(bp); - return new; - -} - -/* - * grow the front of a list of blocks by n bytes - */ -Block * -prepend(Block *bp, int n) -{ - Block *nbp; - - if(bp->base && (bp->rptr - bp->base)>=n){ - /* - * room for channel number in first block of message - */ - bp->rptr -= n; - return bp; - } else { - /* - * make new block, put message number at end - */ - nbp = allocb(2); - nbp->next = bp; - nbp->wptr = nbp->lim; - nbp->rptr = nbp->wptr - n; - return nbp; - } -} - - -/* - * put a block into the bit bucket - */ -void -nullput(Queue *q, Block *bp) -{ - USED(q); - if(bp->type == M_HANGUP) - freeb(bp); - else { - freeb(bp); - error(Ehungup); - } -} - -/* - * find the info structure for line discipline 'name' - */ -Qinfo * -qinfofind(char *name) -{ - Qinfo *qi; - - if(name == 0) - return 0; - for(qi = lds; qi; qi = qi->next) - if(strcmp(qi->name, name)==0) - return qi; - return 0; -} - -/* - * send a hangup up a stream - */ -static void -hangup(Stream *s) -{ - Block *bp; - - bp = allocb(0); - bp->type = M_HANGUP; - (*s->devq->put)(s->devq, bp); + q->first = bp->next; + if(q->first == 0) + q->last = 0; + q->len -= BLEN(bp); + bp->next = 0; + } + return bp; } + /* - * parse a string and return a pointer to the second element if the - * first matches name. bp->rptr will be updated to point to the - * second element. - * - * return 0 if no match. - * - * it is assumed that the block data is null terminated. streamwrite - * guarantees this. + * put a block into the bit bucket */ -int -streamparse(char *name, Block *bp) +void +nullput(Queue *q, Block *bp) { - int len; - - len = strlen(name); - if(BLEN(bp) < len) - return 0; - if(strncmp(name, (char *)bp->rptr, len)==0){ - if(bp->rptr[len] == ' ') - bp->rptr += len+1; - else if(bp->rptr[len]) - return 0; - else - bp->rptr += len; - while(*bp->rptr==' ' && bp->wptr>bp->rptr) - bp->rptr++; - return 1; + USED(q); + if(bp->type == M_HANGUP) + freeb(bp); + else { + freeb(bp); + error(Ehungup); } - return 0; } +/* + * Part 3) Streams + */ + /* * the per stream directory structure */ @@ -651,6 +607,34 @@ Dirtab streamdir[]={ "ctl", {Sctlqid}, 0, 0600, }; +/* + * hash buckets containing all streams + */ +enum +{ + Nbits= 5, + Nhash= 1<inuse == 0){ - if(canqlock(s)){ - if(s->inuse == 0) - break; + qlock(hb); + for(s = hb->s; s; s = s->next) { + if(s->type == type && s->dev == dev && s->id == id){ + s->inuse++; + qunlock(hb); + if(noopen == 0){ + qlock(s); + s->opens++; qunlock(s); } + return s; } } - if(s == &slist[conf.nstream]){ - print("no more streams\n"); - exhausted("streams"); - } - if(waserror()){ - qunlock(s); - streamclose1(s); - nexterror(); - } /* - * identify the stream + * create and init a new stream */ + s = smalloc(sizeof(Stream)); + s->inuse = 1; s->type = type; s->dev = dev; s->id = id; s->err = 0; + s->hread = 0; + s->next = hb->s; + hb->s = s; + + /* + * The ordering of these 2 instructions is very important. + * It makes sure we finish the stream initialization before + * anyone else can access it. + */ + qlock(s); + qunlock(hb); + + if(waserror()){ + qunlock(s); + streamclose1(s); + nexterror(); + } /* * hang a device and process q off the stream */ - s->inuse = 1; if(noopen) s->opens = 0; else s->opens = 1; - s->hread = 0; q = allocq(&procinfo); WR(q)->ptr = s; RD(q)->ptr = s; @@ -745,72 +753,58 @@ streamnew(ushort type, ushort dev, ushort id, Qinfo *qi, int noopen) } /* - * (Re)open a stream. If this is the first open, create a stream. + * Associate a stream with a channel */ void streamopen(Chan *c, Qinfo *qi) { - Stream *s; - Queue *q; - - /* - * if the stream already exists, just increment the reference counts. - */ - for(s = slist; s < &slist[conf.nstream]; s++) { - if(s->inuse && s->type == c->type && s->dev == c->dev - && s->id == STREAMID(c->qid.path)){ - qlock(s); - if(s->inuse && s->type == c->type - && s->dev == c->dev - && s->id == STREAMID(c->qid.path)){ - s->inuse++; - s->opens++; - c->stream = s; - qunlock(s); - return; - } - qunlock(s); - } - } - - /* - * create a new stream - */ c->stream = streamnew(c->type, c->dev, STREAMID(c->qid.path), qi, 0); } /* - * Enter a stream. Increment the reference count so it can't disappear - * under foot. + * Enter a stream only if the stream exists and is open. Increment the + * reference count so it can't disappear under foot. + * + * Return -1 if the stream no longer exists or is not opened. */ int streamenter(Stream *s) { - qlock(s); - if(s->opens == 0){ - qunlock(s); - return -1; - } - s->inuse++; - qunlock(s); - return 0; + Sthash *hb; + Stream *ns; + + hb = hash(s->type, s->dev, s->id); + qlock(hb); + for(ns = hb->s; ns; ns = ns->next) + if(s->type == ns->type && s->dev == ns->dev && s->id == ns->id){ + s->inuse++; + qunlock(hb); + if(s->opens == 0){ + streamexit(s, 1); + return -1; + } + return 0; + } + qunlock(hb); + return -1; } /* * Decrement the reference count on a stream. If the count is * zero, free the stream. */ -int +void streamexit(Stream *s, int locked) { Queue *q; Queue *nq; - int rv; char *name; + Sthash *hb; + Stream **l, *ns; - if(!locked) - qlock(s); - if(s->inuse == 1){ + hb = hash(s->type, s->dev, s->id); + qlock(hb); + if(s->inuse-- == 1){ if(s->opens != 0) panic("streamexit %d %s\n", s->opens, s->devq->info->name); @@ -821,20 +815,28 @@ streamexit(Stream *s, int locked) nq = q->next; freeq(q); } - s->id = s->dev = s->type = 0; if(s->err) freeb(s->err); + + /* + * unchain it from the hash bucket and free + */ + l = &hb->s; + for(ns = hb->s; ns; ns = ns->next){ + if(s == ns){ + *l = s->next; + break; + } + l = &ns->next; + } + free(s); } - s->inuse--; - rv = s->inuse; - if(!locked) - qunlock(s); - return rv; + qunlock(hb); } /* - * On the last close of a stream, for each queue on the - * stream release its blocks and call its close routine. + * Decrement the open count. When it goes to zero, call the close + * routines for each queue in the stream. */ int streamclose1(Stream *s) @@ -844,10 +846,10 @@ streamclose1(Stream *s) int rv; /* - * decrement the reference count + * decrement the open count */ qlock(s); - if(s->opens == 1){ + if(s->opens-- == 1){ /* * descend the stream closing the queues */ @@ -874,13 +876,13 @@ streamclose1(Stream *s) flushq(q); } } - rv = --(s->opens); + rv = s->opens; + qunlock(s); /* * leave it and free it */ streamexit(s, 1); - qunlock(s); return rv; } int @@ -939,38 +941,20 @@ stputq(Queue *q, Block *bp) wakeup(q->rp); } -/* - * read a string. update the offset accordingly. - */ -long -stringread(uchar *buf, long n, char *str, ulong offset) -{ - long i; - - i = strlen(str); - i -= offset; - if(istream; if(STREAMTYPE(c->qid.path) == Sctlqid){ sprint(num, "%d", s->id); - return stringread(buf, n, num, c->offset); + return readstr(c->offset, buf, n, num); } else { if(CHDIR & c->qid.path) return devdirread(c, vbuf, n, 0, 0, streamgen); @@ -1244,26 +1228,6 @@ streamwrite(Chan *c, void *a, long n, int docopy) return n; } -/* - * like andrew's getmfields but no hidden state - */ -int -getfields(char *lp, char **fields, int n, char sep) -{ - int i; - - for(i=0; lp && *lp && iwptr, bp->rptr, l); - nb->wptr += l; - count -= l; - if(bp->flags & S_DELIM) - nb->flags |= S_DELIM; - *p = nb; - p = &nb->next; - bp = bp->next; - if(bp == 0) - break; - } - if(count) { - nb = allocb(count); - if(nb == 0) - panic("copyb.2"); - memset(nb->wptr, 0, count); - nb->wptr += count; - nb->flags |= S_DELIM; - *p = nb; - } - if(blen(head) == 0) - print("copyb: zero length\n"); + bp = allocb(0); + bp->type = M_HANGUP; + (*s->devq->put)(s->devq, bp); +} - return head; +/* + * parse a string and return a pointer to the second element if the + * first matches name. bp->rptr will be updated to point to the + * second element. + * + * return 0 if no match. + * + * it is assumed that the block data is null terminated. streamwrite + * guarantees this. + */ +int +streamparse(char *name, Block *bp) +{ + int len; + + len = strlen(name); + if(BLEN(bp) < len) + return 0; + if(strncmp(name, (char *)bp->rptr, len)==0){ + if(bp->rptr[len] == ' ') + bp->rptr += len+1; + else if(bp->rptr[len]) + return 0; + else + bp->rptr += len; + while(*bp->rptr==' ' && bp->wptr>bp->rptr) + bp->rptr++; + return 1; + } + return 0; } /* - * Dump all block information of how many blocks are in which queues + * like andrew's getmfields but no hidden state */ -void -dumpblocks(Queue *q, char c) +int +getfields(char *lp, char **fields, int n, char sep) { - Block *bp; - uchar *cp; + int i; - lock(q); - for(bp = q->first; bp; bp = bp->next){ - print("%c %c%d%c", c, bp->type == M_DATA ? 'd' : 'c', - bp->wptr-bp->rptr, (bp->flags&S_DELIM)?'D':' '); - for(cp = bp->rptr; cpwptr && cprptr+30; cp++) - print(" %.2x", *cp); - print("\n"); + for(i=0; lp && *lp && iflag & QINUSE)) - continue; - qcount++; - print("%10s %ux R n %d l %d f %ux r %ux ", - q->info->name, q, - q->nb, q->len, q->flag, &(q->r)); - print(" W n %d l %d f %ux r %ux next %lux put %lux Rz %lux", - WR(q)->nb, WR(q)->len, - WR(q)->flag, &(WR(q)->r), q->next, q->put, q->rp); - print("\n"); - dumpblocks(q, 'R'); - dumpblocks(WR(q), 'W'); - } - print("%d queues\n", qcount); } diff --git a/port/sturp.c b/port/sturp.c index 4913d5a2913b3ecedb11f5112536a5605a437d13..c9b24d60dd59554d6479dafb155243eac1475a9f 100644 --- a/port/sturp.c +++ b/port/sturp.c @@ -34,6 +34,7 @@ struct urpstat { struct Urp { QLock; + Urp *list; /* list of all urp structures */ short state; /* flags */ Rendez r; /* process waiting for output to finish */ @@ -60,7 +61,13 @@ struct Urp { ulong timer; /* timeout for xmit */ int rexmit; }; -Urp *urp; + +/* list of allocated urp structures (never freed) */ +struct +{ + Lock; + Urp *urp; +} urpalloc; Rendez urpkr; QLock urpkl; @@ -135,7 +142,6 @@ Qinfo urpinfo = static void urpreset(void) { - urp = (Urp *)xalloc(conf.nurp*sizeof(Urp)); } static void @@ -155,9 +161,9 @@ urpopen(Queue *q, Stream *s) } /* - * find a free urp structure + * find an unused urp structure */ - for(up = urp; up < &urp[conf.nurp]; up++){ + for(up = urpalloc.urp; up; up = up->list){ if(up->state == 0){ qlock(up); if(up->state == 0) @@ -165,15 +171,17 @@ urpopen(Queue *q, Stream *s) qunlock(up); } } - if(up == &urp[conf.nurp]){ - q->ptr = 0; - WR(q)->ptr = 0; - exhausted("urp structures"); + if(up == 0){ + /* + * none available, create a new one, they are never freed + */ + up = smalloc(sizeof(Urp)); + qlock(up); + lock(&urpalloc); + up->list = urpalloc.urp; + urpalloc.urp = up; + unlock(&urpalloc); } -/* - q->flag |= QDEBUG; - q->other->flag |= QDEBUG; -*/ q->ptr = q->other->ptr = up; q->rp = &urpkr; up->rq = q; @@ -993,16 +1001,15 @@ initinput(Urp *up, int window) static void urpkproc(void *arg) { - Urp *up, *eup; + Urp *up; USED(arg); if(waserror()) ; - eup = urp + conf.nurp; for(;;){ - for(up = urp; up < eup; up++){ + for(up = urpalloc.urp; up; up = up->list){ if(up->state==0 || (up->state&HUNGUP)) continue; if(!canqlock(up)) @@ -1044,17 +1051,6 @@ urpvomit(char *msg, Urp* up) up->rq->next->len); } -int -urpdump(void) -{ - Urp *up; - - for(up = urp; up < &urp[conf.nurp]; up++) - if(up->rq) - urpvomit("", up); - return 0; -} - void urpfillstats(Chan *c, char *buf, int len) { diff --git a/port/sysproc.c b/port/sysproc.c index 3aa8ff6e0a343d692b26ccb4df80ab508b92a547..ae79fd4ddcdb9037fd6115b84b3b41327d5f0ef1 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -51,7 +51,8 @@ sysrfork(ulong *arg) if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG)) error(Ebadarg); oeg = p->egrp; - p->egrp = newegrp(); + p->egrp = smalloc(sizeof(Egrp)); + p->egrp->ref = 1; if(flag & RFENVG) envcpy(p->egrp, oeg); closeegrp(oeg); @@ -64,7 +65,8 @@ sysrfork(ulong *arg) else if(flag & RFCFDG) { ofg = p->fgrp; - p->fgrp = newfgrp(); + p->fgrp = smalloc(sizeof(Fgrp)); + p->fgrp->ref = 1; closefgrp(ofg); } if(flag & RFNOTEG) @@ -110,8 +112,10 @@ sysrfork(ulong *arg) if(flag & (RFFDG|RFCFDG)) { if(flag & RFFDG) p->fgrp = dupfgrp(parent->fgrp); - else - p->fgrp = newfgrp(); + else { + p->fgrp = smalloc(sizeof(Fgrp)); + p->fgrp->ref = 1; + } } else { p->fgrp = parent->fgrp; @@ -136,12 +140,10 @@ sysrfork(ulong *arg) /* Environment group */ if(flag & (RFENVG|RFCENVG)) { - if(flag & RFENVG) { - p->egrp = newegrp(); + p->egrp = smalloc(sizeof(Egrp)); + p->egrp->ref = 1; + if(flag & RFENVG) envcpy(p->egrp, parent->egrp); - } - else - p->egrp = newegrp(); } else { p->egrp = parent->egrp; diff --git a/power/conf.h b/power/conf.h index cd4b4293b3eae720fcedd644d9a0299045ae22a7..74e4adbf44253893f8b525d05fb25dddd953f86c 100644 --- a/power/conf.h +++ b/power/conf.h @@ -4,16 +4,9 @@ Conftab conftab[] = { {"npage0", &conf.npage0 }, {"npage1", &conf.npage1 }, {"npage", &conf.npage }, + {"upages", &conf.upages }, {"nimage", &conf.nimage }, {"nswap", &conf.nswap }, - {"nenv", &conf.nenv }, - {"nenvchar", &conf.nenvchar }, - {"npgenv", &conf.npgenv }, - {"nstream", &conf.nstream }, - {"nqueue", &conf.nqueue }, - {"nsrv", &conf.nsrv }, - {"nurp", &conf.nurp }, - {"nasync", &conf.nasync }, {"base0", &conf.base0 }, {"base1", &conf.base1 }, {"copymode", &conf.copymode }, diff --git a/power/dat.h b/power/dat.h index a588112f71837d43d73ed4519c89cd873764f0dd..64ac706acde105c6096a2ba60ec1c9240022ae57 100644 --- a/power/dat.h +++ b/power/dat.h @@ -43,14 +43,6 @@ struct Conf ulong upages; /* user page pool */ ulong nimage; /* number of page cache image headers */ ulong nswap; /* number of swap pages */ - ulong nenv; /* distinct environment values */ - ulong nenvchar; /* environment text storage */ - ulong npgenv; /* environment files per process group */ - ulong nstream; /* streams */ - ulong nqueue; /* stream queues */ - ulong nsrv; /* public servers (devsrv.c) */ - ulong nurp; /* max urp conversations */ - ulong nasync; /* number of async protocol modules */ ulong base0; /* base of bank 0 */ ulong base1; /* base of bank 1 */ ulong copymode; /* 0 is copy on write, 1 is copy on reference */ diff --git a/power/devhs.c b/power/devhs.c index 37ed13e7022abdc90ccea5e8913cb19bc7d79b58..27b724c09804f820ecd233210048bbc398653eea 100644 --- a/power/devhs.c +++ b/power/devhs.c @@ -341,6 +341,13 @@ hsoput(Queue *q, Block *bp) freeb(bp); return; } + if(BLEN(bp) < 3){ + bp = pullup(bp, 3); + if(bp == 0){ + print("hsoput pullup failed\n"); + return; + } + } /* * get a whole message before handing bytes to the device @@ -363,12 +370,6 @@ hsoput(Queue *q, Block *bp) * parse message */ bp = getq(q); - if(bp->wptr - bp->rptr < 3){ - freemsg(q, bp); - qunlock(&hp->xmit); - poperror(); - return; - } chan = CHNO | bp->rptr[0] | (bp->rptr[1]<<8); ctl = bp->rptr[2]; bp->rptr += 3; diff --git a/power/main.c b/power/main.c index c381d93a8d499d5b5c55f1c4a0d21519ce8b404e..6f252040d0a53b39d811b994721575d9ca97dc4d 100644 --- a/power/main.c +++ b/power/main.c @@ -30,7 +30,6 @@ main(void) printinit(); duartspecial(0, &printq, &kbdq, 9600); pageinit(); -xsummary(); tlbinit(); vecinit(); procinit0(); @@ -536,15 +535,9 @@ confinit(void) */ conf.nmach = 1; conf.nproc = 100; - conf.npgenv = 4 * conf.nproc; - conf.nenv = 4 * conf.nproc; - conf.nenvchar = 20 * conf.nenv; conf.nswap = 262144; conf.nimage = 200; - conf.nstream = 2 * conf.nproc; - conf.nurp = 25; conf.dkif = 1; - conf.nqueue = 5 * conf.nstream; conf.ipif = 8; conf.ip = 64; conf.arp = 32; diff --git a/ss/dat.h b/ss/dat.h index c2821c26ded6c712a426e1583025dbe39c3d5901..ad2d9ad7db4ac273198c2619a5509543b41546a4 100644 --- a/ss/dat.h +++ b/ss/dat.h @@ -67,16 +67,6 @@ struct Conf ulong nimage; /* number of page cache image headers */ ulong nswap; /* number of swap blocks */ ulong upages; /* number of user pages */ - int nenv; /* distinct environment values */ - int nenvchar; /* environment text storage */ - int npgenv; /* environment files per process group */ - int nstream; /* streams */ - int nqueue; /* stream queues */ - int nsrv; /* public servers (devsrv.c) */ - int nbitmap; /* bitmap structs (devbit.c) */ - int nbitbyte; /* bytes of bitmap data (devbit.c) */ - int nfont; /* GFont structs (devbit.c) */ - int nsubfont; /* Gsubfont structs (devbit.c) */ int nurp; /* max urp conversations */ int nasync; /* number of async protocol modules */ int copymode; /* 0 is copy on write, 1 is copy on reference */ diff --git a/ss/main.c b/ss/main.c index 4d2f4380be9c0b7a2e88f6376afae372b1fd5da1..d494fc71549dc9724fd3268c0f4c59e91f2848e8 100644 --- a/ss/main.c +++ b/ss/main.c @@ -128,8 +128,10 @@ userinit(void) p = newproc(); p->pgrp = newpgrp(); - p->egrp = newegrp(); - p->fgrp = newfgrp(); + p->egrp = smalloc(sizeof(Egrp)); + p->egrp->ref = 1; + p->fgrp = smalloc(sizeof(Fgrp)); + p->fgrp->ref = 1; p->procmode = 0640; strcpy(p->text, "*init*"); @@ -210,13 +212,6 @@ confinit(void) conf.nproc = 50*mul; conf.nswap = 4096; conf.nimage = 50; - conf.nenv = 100*mul; - conf.nenvchar = 8000*mul; - conf.npgenv = 200*mul; - conf.nstream = 40 + 32*mul; - conf.nqueue = 5 * conf.nstream; - conf.nurp = 32; - conf.nasync = 1; conf.copymode = 0; /* copy on write */ conf.ipif = 8; conf.ip = 64;