M gnot/dat.h => gnot/dat.h +6 -2
@@ 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
M gnot/devdk.c => gnot/devdk.c +3 -5
@@ 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;
}
M gnot/devpipe.c => gnot/devpipe.c +1 -2
@@ 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);
}
M gnot/lock.c => gnot/lock.c +23 -9
@@ 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
M gnot/stream.c => gnot/stream.c +16 -11
@@ 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){
M gnot/sturp.c => gnot/sturp.c +7 -9
@@ 253,7 253,7 @@ urpciput(Queue *q, Block *bp)
/*
* take care of any data
*/
- if(BLEN(bp)>0 && q->next->len<Streamhi)
+ if(BLEN(bp)>0 && !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;
M port/devdk.c => port/devdk.c +2 -0
@@ 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;
}
M port/devpipe.c => port/devpipe.c +6 -2
@@ 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);
}
M port/stream.c => port/stream.c +18 -12
@@ 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){
M port/sturp.c => port/sturp.c +21 -12
@@ 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->len<Streamhi)
+ if(BLEN(bp)>0 && !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;
}
M power/dat.h => power/dat.h +5 -1
@@ 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
M power/devhs.c => power/devhs.c +5 -5
@@ 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);
/*