M gnot/chan.c => gnot/chan.c +20 -10
@@ 149,7 149,7 @@ mount(Chan *new, Chan *old, int flag)
Mtab *mt, *mz;
Mount *mnt, *omnt, *nmnt, *pmnt;
Pgrp *pg;
- int isnew;
+ int islast;
if(CHDIR & (old->qid^new->qid))
error(0, Emount);
@@ 157,10 157,15 @@ mount(Chan *new, Chan *old, int flag)
error(0, Emount);
mz = 0;
- isnew = 0;
+ islast = 0;
+ mnt = 0;
pg = u->p->pgrp;
lock(pg);
if(waserror()){
+ if(mnt){
+ mnt->c = 0; /* caller will close new */
+ closemount(mnt);
+ }
unlock(pg);
nexterror();
}
@@ 171,18 176,18 @@ mount(Chan *new, Chan *old, int flag)
for(i=0; i<pg->nmtab; i++,mt++){
if(mt->c==0 && mz==0)
mz = mt;
- else if(eqchan(mt->c, old, CHDIR|QPATH))
+ else if(eqchan(mt->c, old, CHDIR|QPATH)){
+ mz = 0;
goto Found;
+ }
}
- isnew = 1;
if(mz == 0){
if(i == conf.nmtab)
error(0, Enomount);
mz = &pg->mtab[i];
- pg->nmtab++;
+ islast++;
}
mz->mnt = 0;
- mz->c = old;
mt = mz;
Found:
@@ 244,8 249,12 @@ mount(Chan *new, Chan *old, int flag)
}
incref(new);
- if(isnew)
+ if(mz){
+ mz->c = old;
incref(old);
+ }
+ if(islast)
+ pg->nmtab++;
unlock(pg);
poperror();
return mnt->mountid;
@@ 286,7 295,7 @@ domount(Chan *c)
Found:
lock(pg);
if(!eqchan(mt->c, c, CHDIR|QPATH)){ /* table changed underfoot */
- print("domount: changed underfoot?\n");
+ pprint("domount: changed underfoot?\n");
unlock(pg);
return c;
}
@@ 333,7 342,7 @@ walk(Chan *ac, char *name, int domnt)
goto Notfound;
}
if(c->mountid != mnt->mountid){
- print("walk: changed underfoot?\n");
+ pprint("walk: changed underfoot?\n");
unlock(pg);
goto Notfound;
}
@@ 353,6 362,7 @@ walk(Chan *ac, char *name, int domnt)
if(!first)
close(c);
nc->mnt = mnt;
+ nc->mountid = mnt->mountid;
c = nc;
first = 0;
goto Again;
@@ 391,7 401,7 @@ createdir(Chan *c)
}
mnt = c->mnt;
if(c->mountid != mnt->mountid){
- print("createdir: changed underfoot?\n");
+ pprint("createdir: changed underfoot?\n");
error(0, Enocreate);
}
do{
M gnot/clock.c => gnot/clock.c +2 -1
@@ 117,9 117,10 @@ clock(Ureg *ur)
}
unlock(&m->alarmlock);
}
+ kbdclock();
if((ur->sr&SPL(7)) == 0){
spllo();
if(p && p->state==Running)
- sched();
+ checksched();
}
}
M gnot/devcons.c => gnot/devcons.c +32 -3
@@ 30,9 30,15 @@ struct IOQ{
Rendez r;
};
-IOQ kbdq; /* qlock to getc; interrupt putc's */
IOQ lineq; /* lock to getc; interrupt putc's */
+struct{
+ IOQ; /* qlock to getc; interrupt putc's */
+ int c;
+ int repeat;
+ int count;
+}kbdq;
+
void
printinit(void)
{
@@ 142,17 148,18 @@ pprint(char *fmt, ...)
c = u->fd[2];
if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
- return;
+ return 0;
n = sprint(buf, "%s %d: ", u->p->text, u->p->pid);
n = donprint(buf+n, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
qlock(c);
if(waserror()){
qunlock(c);
- return;
+ return 0;
}
(*devtab[c->type].write)(c, buf, n);
c->offset += n;
qunlock(c);
+ poperror();
return n;
}
@@ 185,9 192,15 @@ echo(int c)
* Put character into read queue at interrupt time.
* Always called splhi from proc 0.
*/
+
void
kbdchar(int c)
{
+ if(kbdq.repeat == 1){
+ kbdq.c = c;
+ kbdq.count = 0;
+ kbdq.repeat = 2;
+ }
if(c == '\r')
c = '\n';
echo(c);
@@ 198,6 211,22 @@ kbdchar(int c)
wakeup(&kbdq.r);
}
+void
+kbdrepeat(int rep)
+{
+ if(rep)
+ kbdq.repeat = 1;
+ else
+ kbdq.repeat = 0;
+}
+
+void
+kbdclock(void)
+{
+ if(kbdq.repeat==2 && (++kbdq.count&1))
+ kbdchar(kbdq.c);
+}
+
int
consactive(void)
{
M gnot/devdk.c => gnot/devdk.c +2 -0
@@ 538,6 538,8 @@ Dirtab dksubdir[]={
void
dkreset(void)
{
+ newqinfo(&dkmuxinfo);
+ newqinfo(&urpinfo);
}
/*
M gnot/devincon.c => gnot/devincon.c +32 -26
@@ 23,8 23,9 @@ enum {
Minstation= 2, /* lowest station # to poll */
Maxstation= 15, /* highest station # to poll */
Nincon= 1, /* number of incons */
- Nin= 16, /* Blocks in the input ring */
+ Nin= 64, /* Blocks in the input ring */
Bsize= 128, /* size of an input ring block */
+ Mfifo= 0xff /* a mask, must be 2^n-1, must be > Nin */
};
/*
@@ 631,7 632,7 @@ inconkproc(void *arg)
}
/*
- * drop an input packet on the floor
+ * drop a single packet
*/
static void
droppacket(Device *dev)
@@ 639,17 640,24 @@ droppacket(Device *dev)
int i;
int c;
- screenputc('!');
- while(!(dev->status & RCV_EMPTY)){
- for(i = 0; i < 17; i++){
- c = dev->data_cntl;
- if(c==0)
- break;
- }
+ for(i = 0; i < 17; i++){
+ c = dev->data_cntl;
+ if(c==0)
+ break;
}
}
/*
+ * flush the input fifo
+ */
+static void
+flushfifo(Device *dev)
+{
+ while(!(dev->status & RCV_EMPTY))
+ droppacket(dev);
+}
+
+/*
* advance the queue. if we've run out of staged input blocks,
* drop the packet and return 0. otherwise return the next input
* block to fill.
@@ 657,19 665,20 @@ droppacket(Device *dev)
static Block *
nextin(Incon *ip, unsigned int c)
{
- Block *bp = ip->inb[ip->wi];
+ Block *bp;
int next;
- next = (ip->wi+1)%Nin;
- if(next == ip->ri){
- bp->wptr = bp->base+3;
- droppacket(ip->dev);
- return 0;
- }
+ bp = ip->inb[ip->wi];
bp->base[0] = ip->chan;
bp->base[1] = ip->chan>>8;
bp->base[2] = c;
- ip->wi = next;
+
+ next = (ip->wi+3)%Nin;
+ if(next == ip->ri){
+ bp->wptr = bp->base+3;
+ return bp;
+ }
+ ip->wi = (ip->wi+1)%Nin;
return ip->inb[ip->wi];
}
@@ 690,8 699,8 @@ rdpackets(Incon *ip)
dev = ip->dev;
bp = ip->inb[ip->wi];
if(bp==0){
- droppacket(ip->dev);
- goto done;
+ flushfifo(ip->dev);
+ return;
}
p = bp->wptr;
while(!(dev->status & RCV_EMPTY)){
@@ 699,12 708,14 @@ rdpackets(Incon *ip)
* get channel number
*/
c = (dev->data_cntl)>>8;
+ if(c == 0){
+ droppacket(dev);
+ continue;
+ }
if(ip->chan != c){
if(p - bp->rptr > 3){
bp->wptr = p;
bp = nextin(ip, 0);
- if(bp == 0)
- goto done;
p = bp->wptr;
}
ip->chan = c;
@@ 725,8 736,6 @@ rdpackets(Incon *ip)
*/
bp->wptr = p;
bp = nextin(ip, c);
- if(bp == 0)
- goto done;
p = bp->wptr;
} else {
/* end of packet */
@@ 741,14 750,11 @@ rdpackets(Incon *ip)
if(p + 16 > bp->lim){
bp->wptr = p;
bp = nextin(ip, 0);
- if(bp == 0)
- goto done;
p = bp->wptr;
}
}
bp->wptr = p;
-done:
if(first != ip->wi)/**/
wakeup(&ip->kr);
}
M gnot/fns.h => gnot/fns.h +4 -0
@@ 8,6 8,7 @@ int canqlock(QLock*);
void chaninit(void);
void chandevreset(void);
void chandevinit(void);
+void checksched(void);
void clock(Ureg*);
Chan *clone(Chan*, Chan*);
void close(Chan*);
@@ 58,6 59,8 @@ int incref(Ref*);
void insert(List**, List*, List*);
void isdir(Chan*);
void kbdchar(int);
+void kbdrepeat(int);
+void kbdclock(void);
void kproc(char*, void(*)(void*), void*);
void lock(Lock*);
void lockinit(void);
@@ 76,6 79,7 @@ Orig *neworig(ulong, ulong, int, Chan*);
Page *newpage(int, Orig*, ulong);
Pgrp *newpgrp(void);
Proc *newproc(void);
+void newqinfo(Qinfo*);
char *nextelem(char*, char*);
void nullput(Queue*, Block*);
int openmode(ulong);
M gnot/main.c => gnot/main.c +5 -5
@@ 240,10 240,10 @@ confinit(void)
conf.nmod = 50;
conf.nalarm = 1000;
conf.norig = 50;
- conf.nchan = 100;
- conf.nenv = 50;
- conf.nenvchar = 4000;
- conf.npgenv = 100;
+ conf.nchan = 200;
+ conf.nenv = 100;
+ conf.nenvchar = 8000;
+ conf.npgenv = 200;
conf.nmtab = 50;
conf.nmount = 100;
conf.nmntdev = 5;
@@ 251,6 251,6 @@ confinit(void)
conf.nmnthdr = 10;
conf.nstream = 64;
conf.nqueue = 5 * conf.nstream;
- conf.nblock = 16 * conf.nstream;
+ conf.nblock = 32 * conf.nstream;
conf.nsrv = 32;
}
M gnot/pgrp.c => gnot/pgrp.c +2 -1
@@ 122,7 122,8 @@ closemount(Mount *m)
{
lock(m);
if(m->ref == 1){
- close(m->c);
+ if(m->c)
+ close(m->c);
if(m->next)
closemount(m->next);
unlock(m);
M gnot/proc.c => gnot/proc.c +7 -0
@@ 117,6 117,13 @@ ready(Proc *p)
splx(s);
}
+void
+checksched(void) /* just for efficiency; don't sched if no need */
+{
+ if(runq.head)
+ sched();
+}
+
/*
* Always called spllo
*/
M gnot/screen.c => gnot/screen.c +9 -5
@@ 161,11 161,15 @@ duartintr(void)
c = duart->data;
if(status & (FRM_ERR|OVR_ERR|PAR_ERR))
duart->cmnd = RESET_ERR;
- if(c == 0x7F)
- c = 0xFF; /* VIEW key (bizarre) */
- if(c & 0x80)
- c = keymap[c&0x7F];
- kbdchar(c);
+ if(status & PAR_ERR) /* control word: caps lock (0x4) or repeat (0x10) */
+ kbdrepeat((c&0x10) == 0);
+ else{
+ if(c == 0x7F)
+ c = 0xFF; /* VIEW key (bizarre) */
+ if(c & 0x80)
+ c = keymap[c&0x7F];
+ kbdchar(c);
+ }
}
/*
* Is it 2?
M gnot/stream.c => gnot/stream.c +33 -21
@@ 7,6 7,11 @@
#include "errno.h"
#include "devtab.h"
+enum {
+ Nclass=4, /* number of block classes */
+ Nlds=32, /* max number of pushable line disciplines */
+};
+
/*
* process end line discipline
*/
@@ 15,21 20,21 @@ Qinfo procinfo = { stputq, nullput, 0, 0, "process" };
/*
* line disciplines that can be pushed
- *
- * WARNING: this table should be the result of configuration
- */
-extern Qinfo noetherinfo;
-extern Qinfo dkmuxinfo;
-extern Qinfo urpinfo;
-static Qinfo *lds[] = {
- &dkmuxinfo,
- &urpinfo,
- 0
-};
+ */
+static Qinfo *lds[Nlds+1];
-enum {
- Nclass=4,
-};
+void
+newqinfo(Qinfo *qi)
+{
+ int i;
+
+ for(i=0; i<Nlds && lds[i]; i++)
+ if(lds[i] == qi)
+ return;
+ if(i == Nlds)
+ panic("pushable");
+ lds[i] = qi;
+}
/*
* All stream structures are ialloc'd at boot time
@@ 51,8 56,8 @@ typedef struct {
} Bclass;
Bclass bclass[Nclass]={
{ 0 },
- { 64 },
- { 512 },
+ { 68 },
+ { 260 },
{ 4096 },
};
@@ 88,7 93,6 @@ streaminit(void)
}
}
-
/*
* allocate a block
*/
@@ 169,7 173,8 @@ freeb(Block *bp)
}
bcp->last = bp;
unlock(bcp);
- wakeup(&bcp->r);
+ if(bcp->r.p)
+ wakeup(&bcp->r);
}
/*
@@ 716,30 721,37 @@ streamclose(Chan *c)
void
stputq(Queue *q, Block *bp)
{
- int i;
+ int delim;
if(bp->type == M_HANGUP){
freeb(bp);
q->flag |= QHUNGUP;
q->other->flag |= QHUNGUP;
wakeup(&q->other->r);
+ delim = 1;
} else {
+ delim = 0;
lock(q);
if(q->first)
q->last->next = bp;
else
q->first = bp;
q->len += BLEN(bp);
+ delim = bp->flags & S_DELIM;
while(bp->next) {
bp = bp->next;
q->len += BLEN(bp);
+ delim |= bp->flags & S_DELIM;
}
q->last = bp;
- if(q->len >= Streamhi)
+ if(q->len >= Streamhi){
q->flag |= QHIWAT;
+ delim = 1;
+ }
unlock(q);
}
- wakeup(&q->r);
+ if(delim)
+ wakeup(&q->r);
}
/*
M gnot/sturp.c => gnot/sturp.c +64 -21
@@ 39,12 39,13 @@ struct Urp {
Rendez r; /* process waiting for close */
/* input */
-
+ QLock ack; /* ack lock */
Queue *rq; /* input queue */
uchar iseq; /* last good input sequence number */
uchar lastecho; /* last echo/rej sent */
uchar trbuf[3]; /* trailer being collected */
short trx; /* # bytes in trailer being collected */
+ int blocks;
/* output */
@@ 110,6 111,8 @@ static void sendblock(Urp*, int);
static void rcvack(Urp*, int);
static void flushinput(Urp*);
static void sendctl(Urp*, int);
+static void sendack(Urp*);
+static void sendrej(Urp*);
static void initoutput(Urp*, int);
static void initinput(Urp*, int);
static void urpkproc(void *arg);
@@ 305,10 308,12 @@ urpciput(Queue *q, Block *bp)
case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3:
case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7:
+ qlock(&up->ack);
i = ctl & Nmask;
if(q->next->len < Streamhi)
sendctl(up, up->lastecho = ECHO+i);
up->iseq = i;
+ qunlock(&up->ack);
break;
}
}
@@ 377,7 382,8 @@ urpiput(Queue *q, Block *bp)
case 0:
break;
case ENQ:
- DPRINT("rENQ %uo %uo\n", up->lastecho, ACK+up->iseq);
+ DPRINT("rENQ %d %uo %uo\n", up->blocks, up->lastecho, ACK+up->iseq);
+ up->blocks = 0;
urpstat.enqsr++;
sendctl(up, up->lastecho);
sendctl(up, ACK+up->iseq);
@@ 440,25 446,15 @@ urpiput(Queue *q, Block *bp)
i = ctl & Nmask;
if(up->trx != 3){
urpstat.rjtrs++;
- flushinput(up);
- DPRINT("sREJ1 %d\n", up->iseq);
- if((up->lastecho&~7)==ECHO)
- sendctl(up, up->lastecho = REJ+up->iseq);/**/
+ sendrej(up);
break;
} else if(q->len != up->trbuf[1] + (up->trbuf[2]<<8)){
urpstat.rjpks++;
- DPRINT("sREJ2 %d %d %d\n", up->iseq, q->len,
- up->trbuf[1] + (up->trbuf[2]<<8));
- flushinput(up);
- if((up->lastecho&~7)==ECHO)
- sendctl(up, up->lastecho = REJ+up->iseq);/**/
+ sendrej(up);
break;
} else if(i != ((up->iseq+1)&Nmask)) {
urpstat.rjseq++;
- flushinput(up);
- DPRINT("sREJ3 %d %d\n", i, up->iseq);
- if((up->lastecho&~7)==ECHO)
- sendctl(up, up->lastecho = REJ+up->iseq);/**/
+ sendrej(up);
break;
}
@@ 480,11 476,11 @@ urpiput(Queue *q, Block *bp)
/*
* acknowledge receipt
*/
- if(q->next->len < Streamhi){
- sendctl(up, up->lastecho = ECHO+i);
- wakeup(&up->rq->r);
- }
+ qlock(&up->ack);
up->iseq = i;
+ if(q->next->len < Streamhi)
+ sendctl(up, up->lastecho = ECHO|i);
+ qunlock(&up->ack);
break;
}
}
@@ 636,6 632,53 @@ sendctl(Urp *up, int ctl)
}
/*
+ * send a reject
+ */
+static void
+sendrej(Urp *up)
+{
+ flushinput(up);
+ qlock(&up->ack);
+ if((up->lastecho&~Nmask) == ECHO){
+ DPRINT("REJ %d\n", up->iseq);
+ sendctl(up, up->lastecho = REJ|up->iseq);
+ }
+ qunlock(&up->ack);
+}
+
+/*
+ * send an acknowledge
+ */
+static void
+sendack(Urp *up)
+{
+ Block *bp;
+
+ /*
+ * check the precondition for acking
+ */
+ if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq)
+ return;
+
+ if(!canqlock(&up->ack))
+ return;
+
+ /*
+ * check again now that we've locked
+ */
+ if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq){
+ qunlock(&up->ack);
+ return;
+ }
+
+ /*
+ * send the ack
+ */
+ sendctl(up, up->lastecho = ECHO|up->iseq);
+ qunlock(&up->ack);
+}
+
+/*
* send a block.
*/
static void
@@ 801,6 844,7 @@ initinput(Urp *up, int window)
/*
* restart all sequence parameters
*/
+ up->blocks = 0;
up->trx = 0;
up->iseq = 0;
up->lastecho = ECHO+0;
@@ 832,8 876,7 @@ urpkproc(void *arg)
if(up->state & HUNGUP)
break;
}
- if((up->lastecho&Nmask)!=up->iseq && up->rq->next->len<Streamhi)
- sendctl(up, up->lastecho = ECHO+up->iseq);
+ sendack(up);
output(up);
tsleep(&up->rq->r, todo, up, MSrexmit/2);
}
M gnot/trap.c => gnot/trap.c +1 -0
@@ 270,6 270,7 @@ syscall(Ureg *aur)
ret = -1;
if(!waserror())
ret = (*systab[r0])((ulong*)(sp+BY2WD));
+else print("syscall %d err %d %d\n", r0, u->error.type, u->error.code);
u->nerrlab = 0;
u->p->insyscall = 0;
if(r0 == NOTED) /* ugly hack */
M port/chan.c => port/chan.c +20 -10
@@ 149,7 149,7 @@ mount(Chan *new, Chan *old, int flag)
Mtab *mt, *mz;
Mount *mnt, *omnt, *nmnt, *pmnt;
Pgrp *pg;
- int isnew;
+ int islast;
if(CHDIR & (old->qid^new->qid))
error(0, Emount);
@@ 157,10 157,15 @@ mount(Chan *new, Chan *old, int flag)
error(0, Emount);
mz = 0;
- isnew = 0;
+ islast = 0;
+ mnt = 0;
pg = u->p->pgrp;
lock(pg);
if(waserror()){
+ if(mnt){
+ mnt->c = 0; /* caller will close new */
+ closemount(mnt);
+ }
unlock(pg);
nexterror();
}
@@ 171,18 176,18 @@ mount(Chan *new, Chan *old, int flag)
for(i=0; i<pg->nmtab; i++,mt++){
if(mt->c==0 && mz==0)
mz = mt;
- else if(eqchan(mt->c, old, CHDIR|QPATH))
+ else if(eqchan(mt->c, old, CHDIR|QPATH)){
+ mz = 0;
goto Found;
+ }
}
- isnew = 1;
if(mz == 0){
if(i == conf.nmtab)
error(0, Enomount);
mz = &pg->mtab[i];
- pg->nmtab++;
+ islast++;
}
mz->mnt = 0;
- mz->c = old;
mt = mz;
Found:
@@ 244,8 249,12 @@ mount(Chan *new, Chan *old, int flag)
}
incref(new);
- if(isnew)
+ if(mz){
+ mz->c = old;
incref(old);
+ }
+ if(islast)
+ pg->nmtab++;
unlock(pg);
poperror();
return mnt->mountid;
@@ 286,7 295,7 @@ domount(Chan *c)
Found:
lock(pg);
if(!eqchan(mt->c, c, CHDIR|QPATH)){ /* table changed underfoot */
- print("domount: changed underfoot?\n");
+ pprint("domount: changed underfoot?\n");
unlock(pg);
return c;
}
@@ 333,7 342,7 @@ walk(Chan *ac, char *name, int domnt)
goto Notfound;
}
if(c->mountid != mnt->mountid){
- print("walk: changed underfoot?\n");
+ pprint("walk: changed underfoot?\n");
unlock(pg);
goto Notfound;
}
@@ 353,6 362,7 @@ walk(Chan *ac, char *name, int domnt)
if(!first)
close(c);
nc->mnt = mnt;
+ nc->mountid = mnt->mountid;
c = nc;
first = 0;
goto Again;
@@ 391,7 401,7 @@ createdir(Chan *c)
}
mnt = c->mnt;
if(c->mountid != mnt->mountid){
- print("createdir: changed underfoot?\n");
+ pprint("createdir: changed underfoot?\n");
error(0, Enocreate);
}
do{
M port/devcons.c => port/devcons.c +3 -2
@@ 180,17 180,18 @@ pprint(char *fmt, ...)
c = u->fd[2];
if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR))
- return;
+ return 0;
n = sprint(buf, "%s %d: ", u->p->text, u->p->pid);
n = donprint(buf+n, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
qlock(c);
if(waserror()){
qunlock(c);
- return;
+ return 0;
}
(*devtab[c->type].write)(c, buf, n);
c->offset += n;
qunlock(c);
+ poperror();
return n;
}
M port/devdk.c => port/devdk.c +2 -0
@@ 538,6 538,8 @@ Dirtab dksubdir[]={
void
dkreset(void)
{
+ newqinfo(&dkmuxinfo);
+ newqinfo(&urpinfo);
}
/*
M port/pgrp.c => port/pgrp.c +2 -1
@@ 122,7 122,8 @@ closemount(Mount *m)
{
lock(m);
if(m->ref == 1){
- close(m->c);
+ if(m->c)
+ close(m->c);
if(m->next)
closemount(m->next);
unlock(m);
M port/stream.c => port/stream.c +33 -22
@@ 7,6 7,11 @@
#include "errno.h"
#include "devtab.h"
+enum {
+ Nclass=4, /* number of block classes */
+ Nlds=32, /* max number of pushable line disciplines */
+};
+
/*
* process end line discipline
*/
@@ 15,22 20,21 @@ Qinfo procinfo = { stputq, nullput, 0, 0, "process" };
/*
* line disciplines that can be pushed
- *
- * WARNING: this table should be the result of configuration
- */
-extern Qinfo noetherinfo;
-extern Qinfo dkmuxinfo;
-extern Qinfo urpinfo;
-static Qinfo *lds[] = {
- &noetherinfo,
- &dkmuxinfo,
- &urpinfo,
- 0
-};
+ */
+static Qinfo *lds[Nlds+1];
-enum {
- Nclass=4,
-};
+void
+newqinfo(Qinfo *qi)
+{
+ int i;
+
+ for(i=0; i<Nlds && lds[i]; i++)
+ if(lds[i] == qi)
+ return;
+ if(i == Nlds)
+ panic("pushable");
+ lds[i] = qi;
+}
/*
* All stream structures are ialloc'd at boot time
@@ 52,8 56,8 @@ typedef struct {
} Bclass;
Bclass bclass[Nclass]={
{ 0 },
- { 64 },
- { 512 },
+ { 68 },
+ { 260 },
{ 4096 },
};
@@ 89,7 93,6 @@ streaminit(void)
}
}
-
/*
* allocate a block
*/
@@ 170,7 173,8 @@ freeb(Block *bp)
}
bcp->last = bp;
unlock(bcp);
- wakeup(&bcp->r);
+ if(bcp->r.p)
+ wakeup(&bcp->r);
}
/*
@@ 717,30 721,37 @@ streamclose(Chan *c)
void
stputq(Queue *q, Block *bp)
{
- int i;
+ int delim;
if(bp->type == M_HANGUP){
freeb(bp);
q->flag |= QHUNGUP;
q->other->flag |= QHUNGUP;
wakeup(&q->other->r);
+ delim = 1;
} else {
+ delim = 0;
lock(q);
if(q->first)
q->last->next = bp;
else
q->first = bp;
q->len += BLEN(bp);
+ delim = bp->flags & S_DELIM;
while(bp->next) {
bp = bp->next;
q->len += BLEN(bp);
+ delim |= bp->flags & S_DELIM;
}
q->last = bp;
- if(q->len >= Streamhi)
+ if(q->len >= Streamhi){
q->flag |= QHIWAT;
+ delim = 1;
+ }
unlock(q);
}
- wakeup(&q->r);
+ if(delim)
+ wakeup(&q->r);
}
/*
M port/sturp.c => port/sturp.c +66 -27
@@ 39,12 39,13 @@ struct Urp {
Rendez r; /* process waiting for close */
/* input */
-
+ QLock ack; /* ack lock */
Queue *rq; /* input queue */
uchar iseq; /* last good input sequence number */
uchar lastecho; /* last echo/rej sent */
uchar trbuf[3]; /* trailer being collected */
short trx; /* # bytes in trailer being collected */
+ int blocks;
/* output */
@@ 110,6 111,8 @@ static void sendblock(Urp*, int);
static void rcvack(Urp*, int);
static void flushinput(Urp*);
static void sendctl(Urp*, int);
+static void sendack(Urp*);
+static void sendrej(Urp*);
static void initoutput(Urp*, int);
static void initinput(Urp*, int);
static void urpkproc(void *arg);
@@ 123,8 126,6 @@ urpopen(Queue *q, Stream *s)
int i;
char name[128];
- DPRINT("urpopen\n");
-
/*
* find a free urp structure
*/
@@ 200,13 201,11 @@ urpclose(Queue *q)
i = 7;
rcvack(up, ECHO+i);
qunlock(&up->xmit);
- DPRINT("urpclose(%ux)\n", up);
/*
* kill off the kernel process
*/
wakeup(&up->rq->r);
- DPRINT("urpclosed(%ux)\n", up);
}
/*
@@ 309,10 308,12 @@ urpciput(Queue *q, Block *bp)
case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3:
case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7:
+ qlock(&up->ack);
i = ctl & Nmask;
if(q->next->len < Streamhi)
sendctl(up, up->lastecho = ECHO+i);
up->iseq = i;
+ qunlock(&up->ack);
break;
}
}
@@ 381,7 382,8 @@ urpiput(Queue *q, Block *bp)
case 0:
break;
case ENQ:
- print("rENQ %uo %uo\n", up->lastecho, ACK+up->iseq);
+ DPRINT("rENQ %d %uo %uo\n", up->blocks, up->lastecho, ACK+up->iseq);
+ up->blocks = 0;
urpstat.enqsr++;
sendctl(up, up->lastecho);
sendctl(up, ACK+up->iseq);
@@ 422,7 424,7 @@ urpiput(Queue *q, Block *bp)
case REJ+0: case REJ+1: case REJ+2: case REJ+3:
case REJ+4: case REJ+5: case REJ+6: case REJ+7:
- print("rREJ\n");
+ DPRINT("rREJ\n");
rcvack(up, ctl);
break;
@@ 444,21 446,15 @@ urpiput(Queue *q, Block *bp)
i = ctl & Nmask;
if(up->trx != 3){
urpstat.rjtrs++;
- flushinput(up);
- print("sREJ1 %d\n", up->iseq);
- sendctl(up, up->lastecho = REJ+up->iseq);
+ sendrej(up);
break;
} else if(q->len != up->trbuf[1] + (up->trbuf[2]<<8)){
urpstat.rjpks++;
- flushinput(up);
- print("sREJ2 %d\n", up->iseq);
- sendctl(up, up->lastecho = REJ+up->iseq);
+ sendrej(up);
break;
} else if(i != ((up->iseq+1)&Nmask)) {
urpstat.rjseq++;
- flushinput(up);
- print("sREJ3 %d %d\n", i, up->iseq);
- sendctl(up, up->lastecho = REJ+up->iseq);
+ sendrej(up);
break;
}
@@ 480,12 476,11 @@ urpiput(Queue *q, Block *bp)
/*
* acknowledge receipt
*/
- if(q->next->len < Streamhi){
- sendctl(up, ECHO+i);
- up->lastecho = ECHO+i;
- wakeup(&up->rq->r);
- }
+ qlock(&up->ack);
up->iseq = i;
+ if(q->next->len < Streamhi)
+ sendctl(up, up->lastecho = ECHO|i);
+ qunlock(&up->ack);
break;
}
}
@@ 510,7 505,6 @@ urpctloput(Urp *up, Queue *q, Block *bp)
outwin = strtoul(fields[0], 0, 0);
}
/* initinput(up, inwin); */
- DPRINT("initoutput %d\n", outwin);
initoutput(up, outwin);
freeb(bp);
return;
@@ 596,7 590,7 @@ output(Urp *up)
* if a retransmit time has elapsed since a transmit, send an ENQ
*/
if(up->unechoed != up->next && NOW > up->timer){
- print("sENQ\n");
+ DPRINT("sENQ\n");
up->timer = NOW + MSrexmit;
up->state &= ~REJECTING;
sendctl(up, ENQ);
@@ 638,6 632,53 @@ sendctl(Urp *up, int ctl)
}
/*
+ * send a reject
+ */
+static void
+sendrej(Urp *up)
+{
+ flushinput(up);
+ qlock(&up->ack);
+ if((up->lastecho&~Nmask) == ECHO){
+ DPRINT("REJ %d\n", up->iseq);
+ sendctl(up, up->lastecho = REJ|up->iseq);
+ }
+ qunlock(&up->ack);
+}
+
+/*
+ * send an acknowledge
+ */
+static void
+sendack(Urp *up)
+{
+ Block *bp;
+
+ /*
+ * check the precondition for acking
+ */
+ if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq)
+ return;
+
+ if(!canqlock(&up->ack))
+ return;
+
+ /*
+ * check again now that we've locked
+ */
+ if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq){
+ qunlock(&up->ack);
+ return;
+ }
+
+ /*
+ * send the ack
+ */
+ sendctl(up, up->lastecho = ECHO|up->iseq);
+ qunlock(&up->ack);
+}
+
+/*
* send a block.
*/
static void
@@ 803,6 844,7 @@ initinput(Urp *up, int window)
/*
* restart all sequence parameters
*/
+ up->blocks = 0;
up->trx = 0;
up->iseq = 0;
up->lastecho = ECHO+0;
@@ 826,7 868,6 @@ urpkproc(void *arg)
Urp *up;
up = (Urp *)arg;
- DPRINT("urpkproc started\n");
for(;;){
if(up->state & (HUNGUP|CLOSING)){
@@ 835,12 876,10 @@ urpkproc(void *arg)
if(up->state & HUNGUP)
break;
}
- if((up->lastecho&Nmask)!=up->iseq && up->rq->next->len<Streamhi)
- sendctl(up, up->lastecho = ECHO+up->iseq);
+ sendack(up);
output(up);
tsleep(&up->rq->r, todo, up, MSrexmit/2);
}
- DPRINT("urpkproc exiting %ux\n", up);
up->kstarted = 0;
up->state = 0;
}
M port/sysfile.c => port/sysfile.c +1 -1
@@ 126,7 126,7 @@ unionread(Chan *c, void *va, long n)
mnt = c->mnt;
lock(pg);
if(c->mountid != mnt->mountid){
- print("unionread: changed underfoot?\n");
+ pprint("unionread: changed underfoot?\n");
unlock(pg);
return 0;
}
M power/devbit.c => power/devbit.c +4 -27
@@ 26,21 26,17 @@ enum
WRITE,
};
-long hold, wait, hang;
-
void
bitsend(Bitmsg *bp, ulong cmd, void *addr, ulong count)
{
- do wait++; while(*BITADDR);
+ do; while(*BITADDR);
bp->cmd = cmd;
bp->addr = (ulong)addr;
bp->count = count;
-/* print("%d %lux %d ", cmd, addr, count); /**/
*BITADDR = bp;
wbflush();
- do hold++; while(*BITHOLD);
+ do; while(*BITHOLD);
*BITINTR = 0x20;
-/* print("done\n"); /**/
}
void
@@ 153,21 149,11 @@ bitread(Chan *c, void *buf, long n)
docpy = 1;
}
qunlock(&bit);
- do{
+ do
n = bp->rcount;
- hang++;
- }while(n == 0);
+ while(n == 0);
if(docpy)
memcpy(buf, bit.buf, n);
-if(0 && n > 512){
- int i;
- char *cp=buf;
- for(i=9; i<n; i++)
- if(cp[i] != cp[i-1]){
- print("r %d %x %x\n", i, cp[i-1], cp[i]);
- break;
- }
-}
return n;
}
error(0, Egreg);
@@ 184,15 170,6 @@ bitwrite(Chan *c, void *buf, long n)
case 1:
if(n > sizeof bit.buf)
error(0, Egreg);
-if(0 && n > 512){
- int i;
- char *cp=buf;
- for(i=15; i<n; i++)
- if(cp[i] != cp[i-1]){
- print("w %d %x %x\n", i, cp[i-1], cp[i]);
- break;
- }
-}
qlock(&bit);
if((((ulong)buf)&(KSEGM|3)) == KSEG0)
bitsend(bp, WRITE, buf, n);
M power/fns.h => power/fns.h +1 -0
@@ 97,6 97,7 @@ Orig *neworig(ulong, ulong, int, Chan*);
Page *newpage(int, Orig*, ulong);
Pgrp *newpgrp(void);
Proc *newproc(void);
+void newqinfo(Qinfo*);
char *nextelem(char*, char*);
void newstart(void);
int newtlbpid(Proc*);
M power/main.c => power/main.c +3 -3
@@ 375,9 375,9 @@ confinit(void)
conf.nalarm = 1000;
conf.norig = 500;
conf.nchan = 500;
- conf.nenv = 200;
- conf.nenvchar = 10000;
- conf.npgenv = 200;
+ conf.nenv = 400;
+ conf.nenvchar = 20000;
+ conf.npgenv = 400;
conf.nmtab = 100;
conf.nmount = 500;
conf.nmntdev = 30;