From 280760c931f4c623d06f19fed1c69a0d6604344e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 4 May 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-05-04 --- alphapc/ether2114x.c | 8 +++- bitsy/devuda1341.c | 2 +- ip/tcp.c | 4 +- mpc/devether.c | 2 +- mpc/etherelnk3.c | 19 ++++++-- mpc/etherwavelan.c | 4 +- pc/devether.c | 7 ++- pc/devusb.c | 17 +------ pc/ether2114x.c | 8 +++- pc/ether79c970.c | 4 +- pc/etherelnk3.c | 19 ++++++-- pc/etherwavelan.c | 2 +- port/allocb.c | 69 ++++++++++++--------------- port/chan.c | 2 +- port/devloopback.c | 7 ++- port/devssl.c | 14 +++--- port/devtls.c | 109 ++++++++++++++++++------------------------- port/qio.c | 6 ++- 18 files changed, 152 insertions(+), 151 deletions(-) diff --git a/alphapc/ether2114x.c b/alphapc/ether2114x.c index a70500a0461ef05978e412255b13c65bd4a05e41..efcfb5f70a140a1356abfb8ea88a7591ca93e8c7 100644 --- a/alphapc/ether2114x.c +++ b/alphapc/ether2114x.c @@ -579,7 +579,9 @@ ctlrinit(Ether* ether) */ ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des)); for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ - des->bp = allocb(Rbsz); + des->bp = iallocb(Rbsz); + if(des->bp == nil) + panic("can't allocate ethernet receive ring"); des->status = Own; des->control = Rbsz; des->addr = PCIWADDR(des->bp->rp); @@ -610,7 +612,9 @@ ctlrinit(Ether* ether) bi[i*4+2] = ether->ea[i*2+1]; bi[i*4+3] = ether->ea[i*2]; } - bp = allocb(Eaddrlen*2*16); + bp = iallocb(Eaddrlen*2*16); + if(bp == nil) + panic("can't allocate ethernet setup buffer"); memset(bp->rp, 0xFF, sizeof(bi)); for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi)) memmove(bp->rp+i, bi, sizeof(bi)); diff --git a/bitsy/devuda1341.c b/bitsy/devuda1341.c index 0e19dc46e34959340b146be224fd8f10247c33f9..5bd1b0815651c937eee0e93f87eac10da61f0867 100644 --- a/bitsy/devuda1341.c +++ b/bitsy/devuda1341.c @@ -902,7 +902,7 @@ audioopen(Chan *c, int mode) } mxvolume(); qunlock(&audio); - if (audio.amode == Aread) + if (audio.amode & Aread) sendaudio(&audio.o); if (debug) print("open done\n"); diff --git a/ip/tcp.c b/ip/tcp.c index 2c03b6feae3eecde393f10a55a8bab308e654c8c..7e417422d473289b67b6c221e668bfae70211c42 100644 --- a/ip/tcp.c +++ b/ip/tcp.c @@ -559,8 +559,10 @@ tcpackproc(void *a) for(t = timeo; t != nil; t = t->readynext) { if(loop++ > 10000) panic("tcpackproc2"); - if(t->state == TimerDONE && t->func != nil) + if(t->state == TimerDONE && t->func != nil && !waserror()){ (*t->func)(t->arg); + poperror(); + } } } } diff --git a/mpc/devether.c b/mpc/devether.c index 4dd3d9812fce3b731243cef8b81483c6a8e19dff..e4ff561f47fe44e18d75879f19fbe3840ca9306d 100644 --- a/mpc/devether.c +++ b/mpc/devether.c @@ -243,7 +243,7 @@ static long etherwrite(Chan* chan, void* buf, long n, vlong) { Ether *ether; - Block *bp; + Block *volatile bp; ether = etherxx[chan->dev]; if(NETTYPE(chan->qid.path) != Ndataqid) diff --git a/mpc/etherelnk3.c b/mpc/etherelnk3.c index 944b0ba9b93aa7afffcc30cf2d6174a2bf0c9315..81b3af667e0ff0da745c2b4ccda35f29aec5ad3b 100644 --- a/mpc/etherelnk3.c +++ b/mpc/etherelnk3.c @@ -465,7 +465,9 @@ init905(Ctlr* ctlr) for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){ pd->np = PADDR(&prev->np); pd->control = 0; - bp = allocb(sizeof(Etherpkt)); + bp = iallocb(sizeof(Etherpkt)); + if(bp == nil) + panic("can't allocate ethernet receive ring"); pd->addr = PADDR(bp->rp); pd->len = updnLastFrag|sizeof(Etherpkt); @@ -1194,7 +1196,9 @@ tcmadapter(int port, int irq, int tbdf) Block *bp; Adapter *ap; - bp = allocb(sizeof(Adapter)); + bp = iallocb(sizeof(Adapter)); + if(bp == nil) + return; ap = (Adapter*)bp->rp; ap->port = port; ap->irq = irq; @@ -1809,13 +1813,18 @@ XCVRDEBUG("\n"); ctlr->ndn = Ndn; init905(ctlr); } - else - ctlr->rbp = rbpalloc(allocb); + else{ + ctlr->rbp = rbpalloc(iallocb); + if(ctlr->rbp == nil) + panic("can't reset ethernet: out of memory"); + } outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256)); break; default: - ctlr->rbp = rbpalloc(allocb); + ctlr->rbp = rbpalloc(iallocb); + if(ctlr->rbp == nil) + panic("can't reset ethernet: out of memory"); break; } diff --git a/mpc/etherwavelan.c b/mpc/etherwavelan.c index 03b2d9dafc4e515e8c080c774a9e2af924cea724..040777d339683f1632a25126d549a99a07f26416 100644 --- a/mpc/etherwavelan.c +++ b/mpc/etherwavelan.c @@ -867,7 +867,9 @@ reset(Ether* ether) print("#l%dWaveLAN: slot %d, port 0x%ulX irq %ld type %s\n", ether->ctlrno, slot, ether->port, ether->irq, ether->type); /* create a receive buffer */ - ctlr->rbp = rbpalloc(allocb); + ctlr->rbp = rbpalloc(iallocb); + if(ctlr->rbp == nil) + panic("can't reset ethernet: out of memory"); /* map a piece of memory (Attribute memory) first */ m = pcmmap(slot, 0, 0x5000, 1); diff --git a/pc/devether.c b/pc/devether.c index fc2a51c255f159645505112fe4caacacd71102e7..7a04a23c37be61c0af9c3fc4cd5c500c24c9b3a4 100644 --- a/pc/devether.c +++ b/pc/devether.c @@ -248,7 +248,7 @@ static long etherwrite(Chan* chan, void* buf, long n, vlong) { Ether *ether; - Block *bp; + Block *volatile bp; int nn; ether = etherxx[chan->dev]; @@ -269,8 +269,13 @@ etherwrite(Chan* chan, void* buf, long n, vlong) error(Etoosmall); bp = allocb(n); + if(waserror()){ + freeb(bp); + nexterror(); + } memmove(bp->rp, buf, n); memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen); + poperror(); bp->wp += n; return etheroq(ether, bp); diff --git a/pc/devusb.c b/pc/devusb.c index 8718046c607dd244c3fe5930e7de1a3a3996cc88..07319191bbada0e702a74438171e13d029b50819 100644 --- a/pc/devusb.c +++ b/pc/devusb.c @@ -718,8 +718,8 @@ qrcv(Endpt *e) QH *qh; int vf; - t = alloctde(e, TokIN, e->maxpkt); b = allocb(e->maxpkt); + t = alloctde(e, TokIN, e->maxpkt); t->bp = b; t->buffer = PADDR(b->wp); ub = &ubus; @@ -734,21 +734,6 @@ qrcv(Endpt *e) return qh; } -static Block * -usbreq(int type, int req, int value, int offset, int count) -{ - Block *b; - - b = allocb(8); - b->wp[0] = type; - b->wp[1] = req; - PUT2(b->wp+2, value); - PUT2(b->wp+4, offset); - PUT2(b->wp+6, count); - b->wp += 8; - return b; -} - /* * return smallest power of 2 >= n */ diff --git a/pc/ether2114x.c b/pc/ether2114x.c index 90ad7b3f76b94d6f8cb22192b9554b0f5242028e..d6a3a4674c6946f7d246ae8271ee5b1fdfd858d1 100644 --- a/pc/ether2114x.c +++ b/pc/ether2114x.c @@ -576,7 +576,9 @@ ctlrinit(Ether* ether) */ ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des)); for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ - des->bp = allocb(Rbsz); + des->bp = iallocb(Rbsz); + if(des->bp == nil) + panic("can't allocate ethernet receive ring"); des->status = Own; des->control = Rbsz; des->addr = PADDR(des->bp->rp); @@ -607,7 +609,9 @@ ctlrinit(Ether* ether) bi[i*4+2] = ether->ea[i*2+1]; bi[i*4+3] = ether->ea[i*2]; } - bp = allocb(Eaddrlen*2*16); + bp = iallocb(Eaddrlen*2*16); + if(bp == nil) + panic("can't allocate ethernet setup buffer"); memset(bp->rp, 0xFF, sizeof(bi)); for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi)) memmove(bp->rp+i, bi, sizeof(bi)); diff --git a/pc/ether79c970.c b/pc/ether79c970.c index 35c184622f9b8fbb6805ffd27fc6132b325acad8..d309f14af95eebec6f9a9643af459245e3cb9e43 100644 --- a/pc/ether79c970.c +++ b/pc/ether79c970.c @@ -430,7 +430,9 @@ amd79c970adapter(Block** bpp, int port, int irq, int tbdf) Block *bp; Adapter *ap; - bp = allocb(sizeof(Adapter)); + bp = iallocb(sizeof(Adapter)); + if(bp == nil) + return; ap = (Adapter*)bp->rp; ap->port = port; ap->irq = irq; diff --git a/pc/etherelnk3.c b/pc/etherelnk3.c index 3461ef53fb3eb8023e22532030b498cc171b9d80..dd3d3500cb8b9aff9280319f6182d755cab46fe4 100644 --- a/pc/etherelnk3.c +++ b/pc/etherelnk3.c @@ -467,7 +467,9 @@ init905(Ctlr* ctlr) for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){ pd->np = PADDR(&prev->np); pd->control = 0; - bp = allocb(sizeof(Etherpkt)); + bp = iallocb(sizeof(Etherpkt)); + if(bp == nil) + panic("can't allocate ethernet receive ring"); pd->addr = PADDR(bp->rp); pd->len = updnLastFrag|sizeof(Etherpkt); @@ -1227,7 +1229,9 @@ tcmadapter(int port, int irq, int tbdf) Block *bp; Adapter *ap; - bp = allocb(sizeof(Adapter)); + bp = iallocb(sizeof(Adapter)); + if(bp == nil) + return; ap = (Adapter*)bp->rp; ap->port = port; ap->irq = irq; @@ -2013,13 +2017,18 @@ etherelnk3reset(Ether* ether) ctlr->ndn = Ndn; init905(ctlr); } - else - ctlr->rbp = rbpalloc(allocb); + else { + ctlr->rbp = rbpalloc(iallocb); + if(ctlr->rbp == nil) + panic("can't reset ethernet: out of memory"); + } outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256)); break; default: - ctlr->rbp = rbpalloc(allocb); + ctlr->rbp = rbpalloc(iallocb); + if(ctlr->rbp == nil) + panic("can't reset ethernet: out of memory"); break; } diff --git a/pc/etherwavelan.c b/pc/etherwavelan.c index 87bcea426ab1a800a45456980e002ca693d6b2dd..309bfc3e04073a47b947839e908981fbab8b9856 100644 --- a/pc/etherwavelan.c +++ b/pc/etherwavelan.c @@ -29,7 +29,7 @@ #define DEBUG if(1)print -#define SEEKEYS 1 +#define SEEKEYS 0 typedef struct Ctlr Ctlr; typedef struct Wltv Wltv; diff --git a/port/allocb.c b/port/allocb.c index 989cacfa90f9bc74415e34c3e09afee11074afc0..6d74b7472803ae8bd9137093eb61bc04b08f994d 100644 --- a/port/allocb.c +++ b/port/allocb.c @@ -18,21 +18,19 @@ struct ulong bytes; } ialloc; -/* - * allocate blocks, round the data base up to a multiple of BLOCKALIGN. - */ -Block* -allocb(int size) +static Block* +_allocb(int size) { Block *b; ulong addr; - int n; - n = sizeof(Block) + size; - b = malloc(n+Hdrspc); - if(b == 0) - exhausted("Blocks"); - memset(b, 0, sizeof(Block)); + if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil) + return nil; + + b->next = nil; + b->list = nil; + b->free = 0; + b->flag = 0; /* align start of data portion by rounding up */ addr = (ulong)b; @@ -48,22 +46,34 @@ allocb(int size) /* leave sluff at beginning for added headers */ b->rp = b->lim - ROUND(size, BLOCKALIGN); if(b->rp < b->base) - panic("allocb"); + panic("_allocb"); b->wp = b->rp; + + return b; +} + +Block* +allocb(int size) +{ + Block *b; + + /* + * Check in a process and wait until successful. + * Can still error out of here, though. + */ + if(up == nil) + panic("allocb without up: %uX\n", getcallerpc(&size)); + if((b = _allocb(size)) == nil) + panic("allocb: no memory\n"); setmalloctag(b, getcallerpc(&size)); return b; } -/* - * interrupt time allocation - */ Block* iallocb(int size) { Block *b; - ulong addr; - int n; if(ialloc.bytes > conf.ialloc){ print("iallocb: limited %lud/%lud\n", @@ -71,38 +81,17 @@ iallocb(int size) return 0; } - n = sizeof(Block) + size; - b = malloc(n+Hdrspc); - if(b == 0){ + if((b = _allocb(size)) == nil){ print("iallocb: no memory %lud/%lud\n", ialloc.bytes, conf.ialloc); return nil; } - memset(b, 0, sizeof(Block)); - - /* align start of data portion by rounding up */ - addr = (ulong)b; - addr = ROUND(addr + sizeof(Block), BLOCKALIGN); - b->base = (uchar*)addr; - - /* align end of data portion by rounding down */ - b->lim = ((uchar*)b) + msize(b); - addr = (ulong)(b->lim); - addr = addr & ~(BLOCKALIGN-1); - b->lim = (uchar*)addr; - - /* leave sluff at beginning for added headers */ - b->rp = b->lim - ROUND(size, BLOCKALIGN); - if(b->rp < b->base) - panic("allocb"); - b->wp = b->rp; - + setmalloctag(b, getcallerpc(&size)); b->flag = BINTR; ilock(&ialloc); ialloc.bytes += b->lim - b->base; iunlock(&ialloc); - setmalloctag(b, getcallerpc(&size)); return b; } diff --git a/port/chan.c b/port/chan.c index 8d62ae532221ffe426683802688db882aa784e05..503035fb4a7a77f3ef585198be1075d7f2119468 100644 --- a/port/chan.c +++ b/port/chan.c @@ -195,7 +195,7 @@ cclose(Chan *c) return; if(waserror()){ - print("cclose error: type %C; error %s\n", devtab[c->type]->dc, up!=nil? up->error : "no user"); //BUG +// print("cclose error: type %C; error %s\n", devtab[c->type]->dc, up!=nil? up->error : "no user"); chanfree(c); return; } diff --git a/port/devloopback.c b/port/devloopback.c index c1166ba2d8bb3240fa9ff116e38bb8b74433e7ba..94ae98af44ff930c0904dcda16c07caa2cc6cfbe 100644 --- a/port/devloopback.c +++ b/port/devloopback.c @@ -559,18 +559,23 @@ loopbackwrite(Chan *c, void *va, long n, vlong off) } static long -loopoput(Loop *lb, Link *link, Block *bp) +loopoput(Loop *lb, Link *link, Block *volatile bp) { long n; n = BLEN(bp); /* make it a single block with space for the loopback timing header */ + if(waserror()){ + freeb(bp); + nexterror(); + } bp = padblock(bp, Tmsize); if(bp->next) bp = concatblock(bp); if(BLEN(bp) < lb->minmtu) bp = adjustblock(bp, lb->minmtu); + poperror(); ptime(bp->rp, fastticks(nil)); link->packets++; diff --git a/port/devssl.c b/port/devssl.c index 6ccfa3ccfa9289e0e73323e64c405abf27e92223..b6899fa9b2c5c6de598f47e99c0cf3b3b093c57b 100644 --- a/port/devssl.c +++ b/port/devssl.c @@ -502,11 +502,11 @@ qremove(Block **l, int n, int discard) } /* - * We can't let Eintr's lose data since the program - * doing the read may be able to handle it. The only - * places Eintr is possible is during the read's in consume. - * Therefore, we make sure we can always put back the bytes - * consumed before the last ensure. + * We can't let Eintrs lose data, since doing so will get + * us out of sync with the sender and break the reliablity + * of the channel. Eintr only happens during the reads in + * consume. Therefore we put back any bytes consumed before + * the last call to ensure. */ static Block* sslbread(Chan *c, long n, ulong) @@ -525,8 +525,10 @@ sslbread(Chan *c, long n, ulong) nconsumed = 0; if(waserror()){ - if(strcmp(up->error, Eintr) == 0) + if(strcmp(up->error, Eintr) == 0 && !waserror()){ regurgitate(s.s, consumed, nconsumed); + poperror(); + } qunlock(&s.s->in.q); nexterror(); } diff --git a/port/devtls.c b/port/devtls.c index 8d726c1293a93c62b90ae490577b7d46ed6e07b1..4264dc74af9ad4548abeb27b3be95afd501b8eca 100644 --- a/port/devtls.c +++ b/port/devtls.c @@ -671,51 +671,32 @@ regurgitate(TlsRec *s, uchar *p, int n) } /* - * remove at most n bytes from the queue, if discard is set + * remove at most n bytes from the queue in a single block, if discard is set * dump the remainder */ static Block* -qremove(Block **l, int n, int discard) +qgrab(Block **l, int n) { - Block *nb, *b, *first; + Block *bb, *b; int i; - first = *l; - for(b = first; b; b = b->next){ - i = BLEN(b); - if(i == n){ - if(discard){ - freeblist(b->next); - *l = 0; - } else - *l = b->next; - b->next = 0; - return first; - } else if(i > n){ - i -= n; - if(discard){ - freeblist(b->next); - b->wp -= i; - *l = 0; - } else { - nb = allocb(i); - memmove(nb->wp, b->rp+n, i); - nb->wp += i; - b->wp -= i; - nb->next = b->next; - *l = nb; - } - b->next = 0; - if(BLEN(b) < 0) - panic("qremove"); - return first; - } else - n -= i; - if(BLEN(b) < 0) - panic("qremove"); + b = *l; + if(BLEN(b) == n){ + *l = b->next; + b->next = nil; + return b; } - *l = 0; - return first; + + i = 0; + for(bb = b; bb != nil && i < n; bb = bb->next) + i += BLEN(bb); + if(i > n) + i = n; + + bb = allocb(i); + consume(l, bb->wp, i); + bb->wp += i; + return bb; } static void @@ -731,8 +712,13 @@ tlsclosed(TlsRec *tr, int new) } /* - * read and process one tls record layer message - * must be called with tr->in.io held + * read and process one tls record layer message + * must be called with tr->in.io held + * We can't let Eintrs lose data, since doing so will get + * us out of sync with the sender and break the reliablity + * of the channel. Eintr only happens during the reads in + * consume. Therefore we put back any bytes consumed before + * the last call to ensure. */ static void tlsrecread(TlsRec *tr) @@ -745,9 +731,10 @@ tlsrecread(TlsRec *tr) nconsumed = 0; if(waserror()){ - if(strcmp(up->error, Eintr) == 0) + if(strcmp(up->error, Eintr) == 0 && !waserror()){ regurgitate(tr, header, nconsumed); - else + poperror(); + }else tlsError(tr, "channel error"); nexterror(); } @@ -778,7 +765,7 @@ tlsrecread(TlsRec *tr) tlsError(tr, "channel error"); nexterror(); } - b = qremove(&tr->unprocessed, len, 0); + b = qgrab(&tr->unprocessed, len); in = &tr->in; if(waserror()){ @@ -786,7 +773,6 @@ tlsrecread(TlsRec *tr) nexterror(); } qlock(&in->seclock); - b = pullupblock(b, len); p = b->rp; if(in->sec != nil) { len = (*in->sec->dec)(in->sec, p, len); @@ -874,8 +860,10 @@ tlsrecread(TlsRec *tr) b = nil; poperror(); dechandq(tr); - }else if(tr->verset && tr->version != SSL3Version) + }else if(tr->verset && tr->version != SSL3Version && !waserror()){ sendAlert(tr, ENoRenegotiation); + poperror(); + } break; case RApplication: if(!tr->opened) @@ -938,7 +926,7 @@ rcvError(TlsRec *tr, int err, char *fmt, ...) static void alertHand(TlsRec *tr, char *msg) { - Block *volatile b; + Block *b; int n; lock(&tr->hqlock); @@ -950,10 +938,7 @@ alertHand(TlsRec *tr, char *msg) unlock(&tr->hqlock); n = strlen(msg); - b = nil; if(waserror()){ - if(b != nil) - freeb(b); dechandq(tr); nexterror(); } @@ -995,13 +980,6 @@ checkstate(TlsRec *tr, int ishand, int ok) error("tls improperly configured"); } -/* - * We can't let Eintr's lose data since the program - * doing the read may be able to handle it. The only - * places Eintr is possible is during the read's in consume. - * Therefore, we make sure we can always put back the bytes - * consumed before the last ensure. - */ static Block* tlsbread(Chan *c, long n, ulong offset) { @@ -1031,7 +1009,7 @@ tlsbread(Chan *c, long n, ulong offset) tlsrecread(tr); /* return at most what was asked for */ - b = qremove(&tr->processed, n, 0); + b = qgrab(&tr->processed, n); qunlock(&tr->in.io); poperror(); tr->datain += BLEN(b); @@ -1064,7 +1042,7 @@ tlsbread(Chan *c, long n, ulong offset) } tr->hprocessed = b; } - b = qremove(&tr->hprocessed, n, 0); + b = qgrab(&tr->hprocessed, n); poperror(); qunlock(&tr->hqread); tr->handin += BLEN(b); @@ -1729,12 +1707,15 @@ sendAlert(TlsRec *tr, int err) } } - b = allocb(2); - *b->wp++ = fatal + 1; - *b->wp++ = err; - if(fatal) - tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose); - tlsrecwrite(tr, RAlert, b); + if(!waserror()){ + b = allocb(2); + *b->wp++ = fatal + 1; + *b->wp++ = err; + if(fatal) + tlsSetState(tr, SAlert, SOpen|SHandshake|SRClose); + tlsrecwrite(tr, RAlert, b); + poperror(); + } if(fatal) tlsError(tr, msg); } diff --git a/port/qio.c b/port/qio.c index f06c76e9955585bff9f033a40876955d18b85450..72e65c658d8c498957a23a73c7e8c0f27ef97b0f 100644 --- a/port/qio.c +++ b/port/qio.c @@ -1185,7 +1185,9 @@ qiwrite(Queue *q, void *vp, int len) if(n > Maxatomic) n = Maxatomic; - b = allocb(n); + b = iallocb(n); + if(b == nil) + break; memmove(b->wp, p+sofar, n); b->wp += n; @@ -1216,7 +1218,7 @@ qiwrite(Queue *q, void *vp, int len) sofar += n; } while(sofar < len && (q->state & Qmsg) == 0); - return len; + return sofar; } /*