From 916bb539005a999b8769d5176f1e95c7bd0cf55d Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 3 Apr 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-04-03 --- gnot/dat.h | 8 ++++++-- gnot/devdk.c | 8 +++----- gnot/devpipe.c | 3 +-- gnot/lock.c | 32 +++++++++++++++++++++++--------- gnot/stream.c | 27 ++++++++++++++++----------- gnot/sturp.c | 16 +++++++--------- port/devdk.c | 2 ++ port/devpipe.c | 8 ++++++-- port/stream.c | 30 ++++++++++++++++++------------ port/sturp.c | 33 +++++++++++++++++++++------------ power/dat.h | 6 +++++- power/devhs.c | 10 +++++----- 12 files changed, 113 insertions(+), 70 deletions(-) diff --git a/gnot/dat.h b/gnot/dat.h index 2433dd49d5927d4d4d198dcc745c9ec7da4e7132..43a239bc6c0ecf97b5efc3c04d2e8c8175f17583 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -43,7 +43,7 @@ struct List struct Lock { - char key[1]; /* addr of sync bus semaphore */ + char key; /* addr of sync bus semaphore */ ulong pc; }; @@ -390,6 +390,7 @@ struct Blist { */ struct Queue { Blist; + int nb; /* number of blocks in queue */ int flag; Qinfo *info; /* line discipline definition */ Queue *other; /* opposite direction, same line discipline */ @@ -426,6 +427,8 @@ struct Stream { #define STREAMQID(i,t) (((i)<<5)|(t)) #define PUTNEXT(q,b) (*(q)->next->put)((q)->next, b) #define BLEN(b) ((b)->wptr - (b)->rptr) +#define QFULL(q) ((q)->flag & QHIWAT) +#define FLOWCTL(q) { if(QFULL(q)) flowctl(q); } /* * stream file qid's & high water mark @@ -435,7 +438,8 @@ enum { Sdataqid = Shighqid, Sctlqid = Sdataqid-1, Slowqid = Sctlqid, - Streamhi= (8*1024), /* stream high water mark */ + Streamhi= (9*1024), /* byte count high water mark */ + Streambhi= 16, /* block count high water mark */ }; #define PRINTSIZE 256 diff --git a/gnot/devdk.c b/gnot/devdk.c index 21d2438c162aff3b4835d70fc661023a220c809b..137cb878e43469ca97e49ebed5dc885cb20b1d5c 100644 --- a/gnot/devdk.c +++ b/gnot/devdk.c @@ -417,11 +417,7 @@ dkoput(Queue *q, Block *bp) bp->rptr[0] = line; bp->rptr[1] = line>>8; - if(dp->wq->len >= Streamhi){ - print("dkoput free\n"); - freeb(bp); - } else - PUTNEXT(dp->wq, bp); + PUTNEXT(dp->wq, bp); } /* @@ -1132,6 +1128,8 @@ dklisten(Chan *c) */ if(ts == lp->timestamp){ print("dklisten: repeat timestamp %d\n", lineno); + if(lp->state != Lconnected) + dkanswer(c, lineno, DKbusy); continue; } diff --git a/gnot/devpipe.c b/gnot/devpipe.c index 0c027c00ccf05e6002a2537c26ba02f4cb9f6353..bd5634ffad95fcbbf841640949790cf680b4daad 100644 --- a/gnot/devpipe.c +++ b/gnot/devpipe.c @@ -154,8 +154,7 @@ pipeerrstr(Error *e, char *buf) static void pipeiput(Queue *q, Block *bp) { - if(q->next->len >= Streamhi) - flowctl(q); + FLOWCTL(q); PUTNEXT(q, bp); } diff --git a/gnot/lock.c b/gnot/lock.c index c66fa3e09e93a0669eab5382ee1981b3d692f294..b47155d63db1dc21b9728764b26df3bcfd4c1700 100644 --- a/gnot/lock.c +++ b/gnot/lock.c @@ -4,6 +4,15 @@ #include "dat.h" #include "fns.h" +#define PCOFF -2 + +/* + * N.B. Ken's compiler generates a TAS instruction for the sequence: + * + * if(l->key >= 0){ + * l->key |= 0x80; + * ... + */ void lock(Lock *l) { @@ -12,24 +21,29 @@ lock(Lock *l) /* * Try the fast grab first */ - if(tas(l->key) == 0){ - l->pc = ((ulong*)&l)[-1]; + if(l->key >= 0){ + l->key |= 0x80; + l->pc = ((ulong*)&i)[PCOFF]; return; } for(i=0; i<10000000; i++) - if(tas(l->key) == 0){ - l->pc = ((ulong*)&l)[-1]; + if(l->key >= 0){ + l->key |= 0x80; + l->pc = ((ulong*)&i)[PCOFF]; return; } - l->key[0] = 0; - panic("lock loop %lux pc %lux held by pc %lux\n", l, ((ulong*)&l)[-1], l->pc); + l->key = 0; + panic("lock loop %lux pc %lux held by pc %lux\n", l, ((ulong*)&i)[PCOFF], l->pc); } int canlock(Lock *l) { - if(tas(l->key) == 0){ - l->pc = ((ulong*)&l)[-1]; + int i; + + if(l->key >= 0){ + l->key |= 0x80; + l->pc = ((ulong*)&i)[PCOFF]; return 1; } return 0; @@ -39,7 +53,7 @@ void unlock(Lock *l) { l->pc = 0; - l->key[0] = 0; + l->key = 0; } void diff --git a/gnot/stream.c b/gnot/stream.c index b92e43b9eb4f222ea743f3972f7b468dc31ff78b..f9856ed92df0af6343880fc70f79e0e2453062df 100644 --- a/gnot/stream.c +++ b/gnot/stream.c @@ -145,10 +145,9 @@ allocb(ulong size) lock(bcp); while(bcp->first == 0){ unlock(bcp); - if(loop++ > 10){ + if(loop++ == 10){ dumpqueues(); - dumpstack(); - panic("waiting for blocks\n"); + print("waiting for blocks\n"); } qlock(bcp); tsleep(&bcp->r, isblock, (void *)bcp, 250); @@ -230,12 +229,14 @@ allocq(Qinfo *qi) q->r.p = 0; q->info = qi; q->put = qi->iput; + q->len = q->nb = 0; wq = q->other = q + 1; wq->r.p = 0; wq->info = qi; wq->put = qi->oput; wq->other = q; + wq->len = wq->nb = 0; unlock(q); @@ -323,14 +324,16 @@ putq(Queue *q, Block *bp) else q->first = bp; q->len += BLEN(bp); + q->nb++; delim = bp->flags & S_DELIM; while(bp->next) { bp = bp->next; q->len += BLEN(bp); + q->nb++; delim |= bp->flags & S_DELIM; } q->last = bp; - if(q->len >= Streamhi) + if(q->len >= Streamhi || q->nb >= Streambhi) q->flag |= QHIWAT; unlock(q); return delim; @@ -387,7 +390,8 @@ getq(Queue *q) if(q->first == 0) q->last = 0; q->len -= BLEN(bp); - if((q->flag&QHIWAT) && q->len < Streamhi/2){ + q->nb--; + if((q->flag&QHIWAT) && q->len < Streamhi/2 && q->nb < Streambhi){ wakeup(&q->other->next->other->r); q->flag &= ~QHIWAT; } @@ -762,14 +766,16 @@ stputq(Queue *q, Block *bp) else q->first = bp; q->len += BLEN(bp); + q->nb++; delim = bp->flags & S_DELIM; while(bp->next) { bp = bp->next; q->len += BLEN(bp); + q->nb++; delim |= bp->flags & S_DELIM; } q->last = bp; - if(q->len >= Streamhi){ + if(q->len >= Streamhi || q->nb >= Streambhi){ q->flag |= QHIWAT; delim = 1; } @@ -938,13 +944,12 @@ notfull(void *arg) Queue *q; q = (Queue *)arg; - return q->len < Streamhi; + return !QFULL(q->next); } void flowctl(Queue *q) { - if(q->next->len >= Streamhi) - sleep(&q->r, notfull, q->next); + sleep(&q->r, notfull, q->next); } /* @@ -996,7 +1001,7 @@ streamwrite(Chan *c, void *a, long n, int docopy) * `a' is global to the whole system, just create a * pointer to it and pass it on. */ - flowctl(q); + FLOWCTL(q); bp = allocb(0); bp->rptr = bp->base = (uchar *)a; bp->wptr = bp->lim = (uchar *)a+n; @@ -1009,7 +1014,7 @@ streamwrite(Chan *c, void *a, long n, int docopy) * system buffers and pass the buffers on. */ for(rem = n; ; rem -= i) { - flowctl(q); + FLOWCTL(q); bp = allocb(rem); i = bp->lim - bp->wptr; if(i >= rem){ diff --git a/gnot/sturp.c b/gnot/sturp.c index df558b40ef8db351dfa145226bb4e916416a39e0..6da19f7356502d78297e59d451fb64f82854cb65 100644 --- a/gnot/sturp.c +++ b/gnot/sturp.c @@ -253,7 +253,7 @@ urpciput(Queue *q, Block *bp) /* * take care of any data */ - if(BLEN(bp)>0 && q->next->len0 && !QFULL(q->next)) PUTNEXT(q, bp); else freeb(bp); @@ -311,7 +311,7 @@ urpciput(Queue *q, Block *bp) case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7: qlock(&up->ack); i = ctl & Nmask; - if(q->next->len < Streamhi) + if(!QFULL(q->next)) sendctl(up, up->lastecho = ECHO+i); up->iseq = i; qunlock(&up->ack); @@ -479,7 +479,7 @@ urpiput(Queue *q, Block *bp) */ qlock(&up->ack); up->iseq = i; - if(q->next->len < Streamhi) + if(!QFULL(q->next)) sendctl(up, up->lastecho = ECHO|i); qunlock(&up->ack); break; @@ -622,7 +622,7 @@ sendctl(Urp *up, int ctl) { Block *bp; - if(up->wq->next->len > Streamhi) + if(QFULL(up->wq->next)) return; bp = allocb(1); bp->wptr = bp->lim; @@ -658,7 +658,7 @@ sendack(Urp *up) /* * check the precondition for acking */ - if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq) + if(QFULL(up->rq->next) || (up->lastecho&Nmask)==up->iseq) return; if(!canqlock(&up->ack)) @@ -667,7 +667,7 @@ sendack(Urp *up) /* * check again now that we've locked */ - if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq){ + if(QFULL(up->rq->next) || (up->lastecho&Nmask)==up->iseq){ qunlock(&up->ack); return; } @@ -689,7 +689,7 @@ sendblock(Urp *up, int bn) int n; up->timer = NOW + MSrexmit; - if(up->wq->next->len > Streamhi) + if(QFULL(up->wq->next)) return; /* @@ -804,8 +804,6 @@ initoutput(Urp *up, int window) up->maxblock = window/4; if(up->maxblock < 64) up->maxblock = 64; - if(up->maxblock > Streamhi/4) - up->maxblock = Streamhi/4; up->maxblock -= 4; up->maxout = 3; diff --git a/port/devdk.c b/port/devdk.c index 1596de189450dea05e4f4e24fae5c01c5ca15b3c..137cb878e43469ca97e49ebed5dc885cb20b1d5c 100644 --- a/port/devdk.c +++ b/port/devdk.c @@ -1128,6 +1128,8 @@ dklisten(Chan *c) */ if(ts == lp->timestamp){ print("dklisten: repeat timestamp %d\n", lineno); + if(lp->state != Lconnected) + dkanswer(c, lineno, DKbusy); continue; } diff --git a/port/devpipe.c b/port/devpipe.c index 4e6b2cace5496d679cf69afd501d71f071fc28ff..bd5634ffad95fcbbf841640949790cf680b4daad 100644 --- a/port/devpipe.c +++ b/port/devpipe.c @@ -11,7 +11,7 @@ static void pipeiput(Queue*, Block*); static void pipeoput(Queue*, Block*); static void pipestclose(Queue *); -Qinfo pipeinfo = { pipeiput, pipeoput, 0, pipestclose, "process" }; +Qinfo pipeinfo = { pipeiput, pipeoput, 0, pipestclose, "pipe" }; void pipeinit(void) @@ -154,7 +154,7 @@ pipeerrstr(Error *e, char *buf) static void pipeiput(Queue *q, Block *bp) { - flowctl(q); + FLOWCTL(q); PUTNEXT(q, bp); } @@ -168,6 +168,10 @@ pipeoput(Queue *q, Block *bp) lock(q); if(q->next) pipeiput(q->next, bp); + else{ + print("pipeoput losing block\n"); + freeb(bp); + } unlock(q); } diff --git a/port/stream.c b/port/stream.c index 2adeb5b1006b115080a69e0bf412dbd09f152ebe..b26800edafb68cc7f414a29e3fee99d9556cba8b 100644 --- a/port/stream.c +++ b/port/stream.c @@ -58,7 +58,7 @@ Bclass bclass[Nclass]={ { 0 }, { 68 }, { 260 }, - { 4096 }, + { 1024 }, }; /* @@ -145,10 +145,9 @@ allocb(ulong size) lock(bcp); while(bcp->first == 0){ unlock(bcp); - if(loop++ > 10){ + if(loop++ == 10){ dumpqueues(); - dumpstack(); - panic("waiting for blocks\n"); + print("waiting for blocks\n"); } qlock(bcp); tsleep(&bcp->r, isblock, (void *)bcp, 250); @@ -230,12 +229,14 @@ allocq(Qinfo *qi) q->r.p = 0; q->info = qi; q->put = qi->iput; + q->len = q->nb = 0; wq = q->other = q + 1; wq->r.p = 0; wq->info = qi; wq->put = qi->oput; wq->other = q; + wq->len = wq->nb = 0; unlock(q); @@ -323,14 +324,16 @@ putq(Queue *q, Block *bp) else q->first = bp; q->len += BLEN(bp); + q->nb++; delim = bp->flags & S_DELIM; while(bp->next) { bp = bp->next; q->len += BLEN(bp); + q->nb++; delim |= bp->flags & S_DELIM; } q->last = bp; - if(q->len >= Streamhi) + if(q->len >= Streamhi || q->nb >= Streambhi) q->flag |= QHIWAT; unlock(q); return delim; @@ -369,6 +372,7 @@ putbq(Blist *q, Block *bp) q->last = bp; q->first = bp; q->len += BLEN(bp); + q->nb++; unlock(q); } @@ -387,7 +391,8 @@ getq(Queue *q) if(q->first == 0) q->last = 0; q->len -= BLEN(bp); - if((q->flag&QHIWAT) && q->len < Streamhi/2){ + q->nb--; + if((q->flag&QHIWAT) && q->len < Streamhi/2 && q->nb < Streambhi){ wakeup(&q->other->next->other->r); q->flag &= ~QHIWAT; } @@ -762,14 +767,16 @@ stputq(Queue *q, Block *bp) else q->first = bp; q->len += BLEN(bp); + q->nb++; delim = bp->flags & S_DELIM; while(bp->next) { bp = bp->next; q->len += BLEN(bp); + q->nb++; delim |= bp->flags & S_DELIM; } q->last = bp; - if(q->len >= Streamhi){ + if(q->len >= Streamhi || q->nb >= Streambhi){ q->flag |= QHIWAT; delim = 1; } @@ -938,13 +945,12 @@ notfull(void *arg) Queue *q; q = (Queue *)arg; - return q->len < Streamhi; + return !QFULL(q->next); } void flowctl(Queue *q) { - if(q->next->len >= Streamhi) - sleep(&q->r, notfull, q->next); + sleep(&q->r, notfull, q->next); } /* @@ -996,7 +1002,7 @@ streamwrite(Chan *c, void *a, long n, int docopy) * `a' is global to the whole system, just create a * pointer to it and pass it on. */ - flowctl(q); + FLOWCTL(q); bp = allocb(0); bp->rptr = bp->base = (uchar *)a; bp->wptr = bp->lim = (uchar *)a+n; @@ -1009,7 +1015,7 @@ streamwrite(Chan *c, void *a, long n, int docopy) * system buffers and pass the buffers on. */ for(rem = n; ; rem -= i) { - flowctl(q); + FLOWCTL(q); bp = allocb(rem); i = bp->lim - bp->wptr; if(i >= rem){ diff --git a/port/sturp.c b/port/sturp.c index df558b40ef8db351dfa145226bb4e916416a39e0..62c3fb61b52f3b4c1241cfa342cf9f90bddff77c 100644 --- a/port/sturp.c +++ b/port/sturp.c @@ -207,6 +207,9 @@ urpclose(Queue *q) * kill off the kernel process */ wakeup(&up->rq->r); + + if(up->kstarted == 0) + up->state = 0; } /* @@ -253,7 +256,7 @@ urpciput(Queue *q, Block *bp) /* * take care of any data */ - if(BLEN(bp)>0 && q->next->len0 && !QFULL(q->next)) PUTNEXT(q, bp); else freeb(bp); @@ -311,7 +314,7 @@ urpciput(Queue *q, Block *bp) case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7: qlock(&up->ack); i = ctl & Nmask; - if(q->next->len < Streamhi) + if(!QFULL(q->next)) sendctl(up, up->lastecho = ECHO+i); up->iseq = i; qunlock(&up->ack); @@ -479,7 +482,7 @@ urpiput(Queue *q, Block *bp) */ qlock(&up->ack); up->iseq = i; - if(q->next->len < Streamhi) + if(!QFULL(q->next)) sendctl(up, up->lastecho = ECHO|i); qunlock(&up->ack); break; @@ -572,14 +575,16 @@ output(Urp *up) * fill the transmit buffers */ q = up->wq; - for(bp = getq(q); bp && up->xb[up->nxb]==0; up->nxb = NEXT(up->nxb)){ + for(bp = getq(q); q->first && up->xb[up->nxb]==0; up->nxb = NEXT(up->nxb)){ + if(bp == 0) + bp = getq(q); if(BLEN(bp) > up->maxblock){ nbp = up->xb[up->nxb] = allocb(0); nbp->rptr = bp->rptr; nbp->wptr = bp->rptr = bp->rptr + up->maxblock; } else { up->xb[up->nxb] = bp; - bp = getq(q); + bp = 0; } } if(bp) @@ -622,7 +627,7 @@ sendctl(Urp *up, int ctl) { Block *bp; - if(up->wq->next->len > Streamhi) + if(QFULL(up->wq->next)) return; bp = allocb(1); bp->wptr = bp->lim; @@ -658,7 +663,7 @@ sendack(Urp *up) /* * check the precondition for acking */ - if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq) + if(QFULL(up->rq->next) || (up->lastecho&Nmask)==up->iseq) return; if(!canqlock(&up->ack)) @@ -667,7 +672,7 @@ sendack(Urp *up) /* * check again now that we've locked */ - if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq){ + if(QFULL(up->rq->next) || (up->lastecho&Nmask)==up->iseq){ qunlock(&up->ack); return; } @@ -689,7 +694,7 @@ sendblock(Urp *up, int bn) int n; up->timer = NOW + MSrexmit; - if(up->wq->next->len > Streamhi) + if(QFULL(up->wq->next)) return; /* @@ -804,8 +809,6 @@ initoutput(Urp *up, int window) up->maxblock = window/4; if(up->maxblock < 64) up->maxblock = 64; - if(up->maxblock > Streamhi/4) - up->maxblock = Streamhi/4; up->maxblock -= 4; up->maxout = 3; @@ -870,6 +873,12 @@ urpkproc(void *arg) up = (Urp *)arg; + if(waserror()){ + up->state = 0; + up->kstarted = 0; + wakeup(&up->r); + return; + } for(;;){ if(up->state & (HUNGUP|CLOSING)){ if(isflushed(up)) @@ -881,6 +890,6 @@ urpkproc(void *arg) output(up); tsleep(&up->rq->r, todo, up, MSrexmit/2); } - up->kstarted = 0; up->state = 0; + up->kstarted = 0; } diff --git a/power/dat.h b/power/dat.h index fc69ec4673dcc76013659c5cd042e0de53461268..22ae85938663a6daeb187a194f1a27f982a93566 100644 --- a/power/dat.h +++ b/power/dat.h @@ -407,6 +407,7 @@ struct Blist { */ struct Queue { Blist; + int nb; /* number of blocks in queue */ int flag; Qinfo *info; /* line discipline definition */ Queue *other; /* opposite direction, same line discipline */ @@ -443,6 +444,8 @@ struct Stream { #define STREAMQID(i,t) (((i)<<5)|(t)) #define PUTNEXT(q,b) (*(q)->next->put)((q)->next, b) #define BLEN(b) ((b)->wptr - (b)->rptr) +#define QFULL(q) ((q)->flag & QHIWAT) +#define FLOWCTL(q) { if(QFULL(q)) flowctl(q); } /* * stream file qid's & high water mark @@ -452,7 +455,8 @@ enum { Sdataqid = Shighqid, Sctlqid = Sdataqid-1, Slowqid = Sctlqid, - Streamhi= (9*1024), /* stream high water mark */ + Streamhi= (9*1024), /* byte count high water mark */ + Streambhi= 16, /* block count high water mark */ }; #define PRINTSIZE 256 diff --git a/power/devhs.c b/power/devhs.c index fbe58314e1bf240f13fc8d3dcc448f292bcd01d7..abba2a935e200ae198d9b38691799ae84e4d78d7 100644 --- a/power/devhs.c +++ b/power/devhs.c @@ -158,7 +158,6 @@ hsvmeattach(char *spec) error(0, Ebadarg); hp = &hsvme[i]; hsvmerestart(hp); - print("hsvme [%d] csr %ux\n", i, hp->addr->csr); c = devattach('h', spec); c->dev = i; @@ -466,6 +465,7 @@ hsvmekproc(void *arg) Hsvme *hp; Device *addr; unsigned int c; + int miss; hp = (Hsvme *)arg; addr = hp->addr; @@ -485,15 +485,14 @@ hsvmekproc(void *arg) } /* - * let the fifo fill a bit + * if we loop many times without finding a character, sleep */ - delay(1); - + for(miss = 0; miss < 10; miss++){ /* * 0xFFFF means an empty fifo */ while ((c = addr->data) != 0xFFFF) { -/* print(" %.2uo<-\n", c); /**/ + miss = 0; if(c & CHNO){ c &= 0x1FF; if(hp->chan == c) @@ -518,6 +517,7 @@ hsvmekproc(void *arg) upstream(hp, 0); } } + } qunlock(hp); /*