M port/devmnt.c => port/devmnt.c +34 -16
@@ 553,7 553,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
{
ulong n;
Mntbuf *mbr, *mbw;
- Chan *mntpt;
+ Chan *mntpt, *msg;
int isbit;
mbr = mballoc();
@@ 564,23 564,38 @@ mntxmit(Mnt *m, Mnthdr *mh)
nexterror();
}
n = convS2M(&mh->thdr, mbw->buf);
- qlock(m);
- if(m->msg == 0){
- qunlock(m);
- error(0, Eshutdown);
- }
isbit = 0;
if(devchar[m->msg->type] == 'b')
isbit = 1;
- if(!isbit)
- qlock(m->msg);
+ /*
+ * Avoid qlock for bit, to maximize parallelism
+ */
+ if(isbit){
+ lock(&m->use); /* spin rather than sleep */
+ if((msg = m->msg) == 0){
+ unlock(&m->use);
+ error(0, Eshutdown);
+ }
+ incref(msg);
+ unlock(&m->use);
+ }else{
+ qlock(m);
+ if((msg = m->msg) == 0){
+ qunlock(m);
+ error(0, Eshutdown);
+ }
+ qlock(msg);
+ }
if(waserror()){
- qunlock(m);
- if(!isbit)
- qunlock(m->msg);
+ if(isbit)
+ close(msg);
+ else{
+ qunlock(m);
+ qunlock(msg);
+ }
nexterror();
}
- if((*devtab[m->msg->type].write)(m->msg, mbw->buf, n) != n){
+ if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){
pprint("short write in mntxmit\n");
error(0, Egreg);
}
@@ 588,10 603,13 @@ mntxmit(Mnt *m, Mnthdr *mh)
/*
* Read response
*/
- n = (*devtab[m->msg->type].read)(m->msg, mbr->buf, BUFSIZE);
- qunlock(m);
- if(!isbit)
- qunlock(m->msg);
+ n = (*devtab[msg->type].read)(msg, mbr->buf, BUFSIZE);
+ if(isbit)
+ close(msg);
+ else{
+ qunlock(m);
+ qunlock(msg);
+ }
poperror();
if(convM2S(mbr->buf, &mh->rhdr, n) == 0){
M port/devproc.c => port/devproc.c +7 -0
@@ 82,6 82,7 @@ procreset(void)
Chan*
procattach(char *spec)
{
+ Chan *c;
return devattach('p', spec);
}
@@ 110,6 111,11 @@ procopen(Chan *c, int omode)
Orig *o;
Chan *tc;
+ if(c->qid == CHDIR){
+ if(omode != OREAD)
+ error(0, Eperm);
+ goto done;
+ }
p = proctab(SLOT(c->qid));
if((p->pid&PIDMASK) != PID(c->qid))
Died:
@@ 156,6 162,7 @@ procopen(Chan *c, int omode)
*/
if(p->state != Dead)
c->qid |= (p->pid&PIDMASK)<<PIDSHIFT;
+ done:
c->mode = omode;
c->flag |= COPEN;
c->offset = 0;
M port/proc.c => port/proc.c +75 -25
@@ 165,6 165,9 @@ loop:
unlock(&procalloc);
p->mach = 0;
p->qnext = 0;
+ p->kid = 0;
+ p->sib = 0;
+ p->pop = 0;
p->nchild = 0;
p->child = 0;
p->exiting = 0;
@@ 339,65 342,66 @@ pexit(char *s, int freemem)
{
char status[64];
ulong mypid;
- Proc *p;
+ Proc *p, *c, *k, *l;
Waitmsg w;
int n;
- Chan *c;
+ Chan *ch;
ulong *up, *ucp, *wp;
- mypid = u->p->pid;
+ c = u->p;
+ mypid = c->pid;
if(s)
strcpy(status, s);
else
status[0] = 0;
if(freemem){
freesegs(-1);
- closepgrp(u->p->pgrp);
+ closepgrp(c->pgrp);
close(u->dot);
}
for(n=0; n<=u->maxfd; n++)
- if(c = u->fd[n]) /* assign = */
- close(c);
+ if(ch = u->fd[n]) /* assign = */
+ close(ch);
/*
* Any of my children exiting?
*/
- while(u->p->nchild){
- lock(&u->p->wait.queue);
- if(canlock(&u->p->wait.use)){ /* no child is exiting */
- u->p->exiting = 1;
- unlock(&u->p->wait.use);
- unlock(&u->p->wait.queue);
+ while(c->nchild){
+ lock(&c->wait.queue);
+ if(canlock(&c->wait.use)){ /* no child is exiting */
+ c->exiting = 1;
+ unlock(&c->wait.use);
+ unlock(&c->wait.queue);
break;
}else{ /* must wait for child */
- unlock(&u->p->wait.queue);
+ unlock(&c->wait.queue);
pwait(0);
}
}
- u->p->time[TReal] = MACHP(0)->ticks - u->p->time[TReal];
+ c->time[TReal] = MACHP(0)->ticks - c->time[TReal];
/*
* Tell my parent
*/
- p = u->p->parent;
+ p = c->parent;
if(p == 0)
goto out;
qlock(&p->wait);
lock(&p->wait.queue);
- if(p->pid==u->p->parentpid && !p->exiting){
+ if(p->pid==c->parentpid && !p->exiting){
w.pid = mypid;
strcpy(w.msg, status);
wp = &w.time[TUser];
- up = &u->p->time[TUser];
- ucp = &u->p->time[TCUser];
+ up = &c->time[TUser];
+ ucp = &c->time[TCUser];
*wp++ = (*up++ + *ucp++)*MS2HZ;
*wp++ = (*up++ + *ucp )*MS2HZ;
*wp = (*up )*MS2HZ;
- p->child = u->p;
+ p->child = c;
/*
* Pass info through back door, to avoid huge Proc's
*/
- p->waitmsg = (Waitmsg*)(u->p->upage->pa|(((ulong)&w)&(BY2PG-1))|KZERO);
- u->p->state = Exiting;
+ p->waitmsg = (Waitmsg*)(c->upage->pa|(((ulong)&w)&(BY2PG-1))|KZERO);
+ c->state = Exiting;
if(p->state == Inwait)
ready(p);
unlock(&p->wait.queue);
@@ 408,15 412,61 @@ pexit(char *s, int freemem)
}
out:
if(!freemem){
- u->p->state = Broken;
+ c->state = Broken;
sched(); /* until someone lets us go */
freesegs(-1);
- closepgrp(u->p->pgrp);
+ closepgrp(c->pgrp);
close(u->dot);
}
+
+ /*
+ * Rearrange inheritance hierarchy
+ * 1. my children's pop is now my pop
+ */
+ lock(&c->kidlock);
+ p = c->pop;
+ if(k = c->kid) /* assign = */
+ do{
+ k->pop = p;
+ k = k->sib;
+ }while(k != c->kid);
+
+ /*
+ * 2. cut me from pop's tree
+ */
+ if(p == 0) /* init process only; fix pops */
+ goto done;
+ lock(&p->kidlock);
+ k = p->kid;
+ while(k->sib != c)
+ k = k->sib;
+ if(k == c)
+ p->kid = 0;
+ else{
+ if(p->kid == c)
+ p->kid = c->sib;
+ k->sib = c->sib;
+ }
+
+ /*
+ * 3. pass my children (pop's grandchildren) to pop
+ */
+ if(k = c->kid){ /* assign = */
+ if(p->kid == 0)
+ p->kid = k;
+ else{
+ l = k->sib;
+ k->sib = p->kid->sib;
+ p->kid->sib = l;
+ }
+ }
+ unlock(&p->kidlock);
+ done:
+ unlock(&c->kidlock);
+
lock(&procalloc); /* sched() can't do this */
- lock(&u->p->debug); /* sched() can't do this */
- u->p->state = Moribund;
+ lock(&c->debug); /* sched() can't do this */
+ c->state = Moribund;
sched(); /* never returns */
}
M port/sysproc.c => port/sysproc.c +15 -0
@@ 105,6 105,20 @@ sysfork(ulong *arg)
if(c = u->fd[n]) /* assign = */
incref(c);
/*
+ * Committed. Link into hierarchy
+ */
+ lock(&p->kidlock);
+ lock(&u->p->kidlock);
+ if(u->p->kid == 0){
+ p->sib = p;
+ u->p->kid = p;
+ }else{
+ p->sib = u->p->kid->sib;
+ u->p->kid->sib = p;
+ }
+ unlock(&u->p->kidlock);
+ unlock(&p->kidlock);
+ /*
* Sched
*/
if(setlabel(&p->sched)){
@@ 115,6 129,7 @@ sysfork(ulong *arg)
spllo();
return 0;
}
+ p->pop = u->p;
p->parent = u->p;
p->parentpid = u->p->pid;
p->pgrp = u->p->pgrp;
M power/dat.h => power/dat.h +5 -0
@@ 81,6 81,7 @@ struct Bitmsg
ulong cmd;
ulong addr;
ulong count;
+ ulong rcount;
};
#define CHDIR 0x80000000L
@@ 301,6 302,10 @@ struct Proc
Page *upage; /* BUG: should be unlinked from page list */
Seg seg[NSEG];
ulong pid;
+ Lock kidlock; /* access to kid and sib */
+ Proc *pop; /* some ascendant */
+ Proc *kid; /* some descendant */
+ Proc *sib; /* non-ascendant relatives (circular list) */
int nchild;
QLock wait; /* exiting children to be waited for */
Waitmsg *waitmsg;
M power/devbit.c => power/devbit.c +31 -7
@@ 16,6 16,7 @@ static struct
}bit;
#define BITADDR ((Bitmsg**)(KZERO+0x7C))
+#define BITHOLD ((ulong*)(KZERO+0x78))
#define BITINTR ((char*)(UNCACHED|0x17c12001))
enum
@@ 25,23 26,27 @@ enum
WRITE,
};
+long hold, wait, hang;
+
void
bitsend(Bitmsg *bp, ulong cmd, void *addr, ulong count)
{
+ do wait++; while(*BITADDR);
bp->cmd = cmd;
bp->addr = (ulong)addr;
bp->count = count;
- if(*BITADDR)
- panic("bitsend");
+/* print("%d %lux %d ", cmd, addr, count); /**/
*BITADDR = bp;
wbflush();
+ do hold++; while(*BITHOLD);
*BITINTR = 0x20;
- do; while(*BITADDR);
+/* print("done\n"); /**/
}
void
bitreset(void)
{
+ *BITHOLD = 0;
*BITADDR = 0;
qlock(&bit);
qunlock(&bit);
@@ 94,7 99,6 @@ bitopen(Chan *c, int omode)
qlock(&bit);
if(bit.open){
qunlock(&bit);
-print("multiple bit open\n");
error(0, Einuse);
}
bitsend(bp, RESET, 0, 0);
@@ 135,6 139,7 @@ bitread(Chan *c, void *buf, long n)
int docpy;
bp = &((User*)(u->p->upage->pa|KZERO))->bit;
+ bp->rcount = 0;
switch(c->qid){
case 1:
if(n > sizeof bit.buf)
@@ 148,11 153,21 @@ bitread(Chan *c, void *buf, long n)
docpy = 1;
}
qunlock(&bit);
- do
- n = bp->count;
- while(n == 0);
+ do{
+ n = bp->rcount;
+ hang++;
+ }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);
@@ 169,6 184,15 @@ 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);