M gnot/clock.c => gnot/clock.c +6 -8
@@ 102,7 102,8 @@ clock(Ureg *ur)
p = m->proc;
if(p){
p->pc = ur->pc;
- p->time[p->insyscall]++;
+ if (p->state==Running)
+ p->time[p->insyscall]++;
}
if(canlock(&m->alarmlock)){
if(m->alarm){
@@ 127,12 128,9 @@ clock(Ureg *ur)
}
kbdclock();
mouseclock();
- if((ur->sr&SPL(7)) == 0){
- spllo();
- if(p && p->state==Running){
- checksched();
- if(u->nnote && (ur->sr&SUPER)==0)
- notify(ur);
- }
+ if((ur->sr&SPL(7)) == 0 && p && p->state==Running){
+ sched();
+ if(u->nnote && (ur->sr&SUPER)==0)
+ notify(ur);
}
}
M gnot/dat.h => gnot/dat.h +21 -1
@@ 101,7 101,7 @@ struct Chan
Mount *mnt; /* mount point that derived Chan */
ulong mountid;
int fid; /* for devmnt */
- union{
+ union {
Stream *stream; /* for stream channels */
void *aux;
};
@@ 205,9 205,11 @@ struct KMap
struct Mach
{
int machno; /* physical id of processor */
+ ulong splpc; /* pc of last caller to splhi */
int mmask; /* 1<<m->machno */
ulong ticks; /* of the clock since boot time */
Proc *proc; /* current process on this processor */
+ Proc *lproc; /* last process on this processor */
Label sched; /* scheduler wakeup */
Lock alarmlock; /* access to alarm list */
void *alarm; /* alarms bound to this clock */
@@ 316,6 318,7 @@ struct Proc
Proc *qnext; /* next process on queue for a QLock */
QLock *qlock; /* address of qlock being queued for DEBUG */
int state;
+ int spin; /* spinning instead of unscheduled */
Page *upage; /* BUG: should be unlinked from page list */
Seg seg[NSEG];
ulong bssend; /* initial top of bss seg */
@@ 340,6 343,20 @@ struct Proc
Rendez sleep; /* place for tsleep and syssleep */
int wokeup; /* whether sleep was interrupted */
ulong pc; /* DEBUG only */
+ int kp; /* true if a kernel process */
+};
+
+struct MMU
+{
+ ulong va;
+ ulong pa;
+};
+
+#define NMMU 16
+struct MMUCache
+{
+ ulong next;
+ MMU mmu[NMMU];
};
#define NERR 15
@@ 365,6 382,7 @@ struct User
short nnote;
short notified; /* sysnoted is due */
int (*notify)(void*, char*);
+ MMUCache mc;
void *ureg;
};
@@ 565,3 583,5 @@ extern Dev devtab[];
extern char devchar[];
extern FPsave initfp;
extern Mach mach0;
+
+extern void (*kprofp)(ulong);
M gnot/devdk.c => gnot/devdk.c +8 -13
@@ 499,6 499,14 @@ dkmuxconfig(Dk *dp, Block *bp)
dp->csc = c;
/*
+ * tell datakit we've rebooted. It should close all channels.
+ */
+ if(dp->restart) {
+ DPRINT("dkmuxconfig: restart %s\n", dp->name);
+ dkmesg(dp, T_ALIVE, D_RESTART, 0, 0);
+ }
+
+ /*
* start a process to deal with it
*/
sprint(buf, "csc.%s.%d", dp->name, dp->ncsc);
@@ 1100,9 1108,7 @@ dklisten(Chan *c)
n = streamread(dc, dialstr, sizeof(dialstr)-1);
DPRINT("returns %d\n", n);
if(n <= 0)
-{print("bad n\n");
error(0, Eio);
-}
dialstr[n] = 0;
DPRINT("dialstr = %s\n", dialstr);
@@ 1112,7 1118,6 @@ dklisten(Chan *c)
n = getfields(dialstr, line, 12, '\n');
if (n < 2) {
DPRINT("bad dialstr from dk (1 line)\n");
-print("bad dialstr %d '%s'\n", n, dialstr);
error(0, Eio);
}
@@ 1319,16 1324,6 @@ dkcsckproc(void *a)
dp = (Dk *)a;
/*
- * tell datakit we've rebooted. It should close all channels.
- */
- if(dp->restart) {
- DPRINT("dkcsckproc: restart %s\n", dp->name);
- dkmesg(dp, T_ALIVE, D_RESTART, 0, 0);
- }
- DPRINT("dkcsckproc: closeall %s\n", dp->name);
- dkmesg(dp, T_CHG, D_CLOSEALL, 0, 0);
-
- /*
* loop forever listening
*/
for(;;){
M gnot/fns.h => gnot/fns.h +2 -2
@@ 81,7 81,6 @@ void kmapinit(void);
KMap *kmap(Page*);
int kprint(char*, ...);
void kproc(char*, void(*)(void*), void*);
-void kproftimer(ulong);
void kunmap(KMap*);
void lock(Lock*);
void lockinit(void);
@@ 136,7 135,7 @@ void qlock(QLock*);
void qunlock(QLock*);
void restartprint(Alarm*);
void restfpregs(FPsave*);
-Proc *runproc(void);
+void restore(void);
void savefpregs(FPsave*);
void sched(void);
void schedinit(void);
@@ 151,6 150,7 @@ void sleep(Rendez*, int(*)(void*), void*);
int splhi(void);
int spllo(void);
void splx(int);
+void spldone(void);
Devgen streamgen;
void streamclose(Chan*);
int streamenter(Stream*);
M gnot/l.s => gnot/l.s +5 -0
@@ 45,6 45,8 @@ TEXT touser(SB), $-4
TEXT splhi(SB), $0
+ MOVL m(SB), A0
+ MOVL (A7), 4(A0)
MOVL $0, R0
MOVW SR, R0
MOVW $(SUPER|SPL(7)), SR
@@ 63,6 65,9 @@ TEXT splx(SB), $0
MOVW R0, SR
RTS
+TEXT spldone(SB), $0
+
+ RTS
TEXT flushcpucache(SB), $0
M gnot/main.c => gnot/main.c +3 -7
@@ 101,11 101,7 @@ init0(void)
{
Chan *c;
- u->nerrlab = 0;
- m->proc = u->p;
- u->p->state = Running;
- u->p->mach = m;
- spllo();
+ restore();
chandevinit();
u->slash = (*devtab[0].attach)(0);
@@ 139,14 135,13 @@ userinit(void)
p->pgrp = newpgrp();
strcpy(p->text, "*init*");
strcpy(p->pgrp->user, protouser);
- p->fpstate = FPinit;
/*
* Kernel Stack
*/
p->sched.pc = (ulong)init0;
p->sched.sp = USERADDR+BY2PG-20; /* BUG */
- p->sched.sr = SUPER|SPL(7);
+ p->sched.sr = SUPER|SPL(0);
p->upage = newpage(0, 0, USERADDR|(p->pid&0xFFFF));
/*
@@ 180,6 175,7 @@ userinit(void)
s->minva = UTZERO;
s->maxva = UTZERO+BY2PG;
+ m->proc = p;
ready(p);
}
M gnot/mmu.c => gnot/mmu.c +46 -4
@@ 19,15 19,37 @@ void
mapstack(Proc *p)
{
ulong tlbvirt, tlbphys;
- ulong i;
+ ulong next;
+ MMU *mm, *mn, *me;
if(p->upage->va != (USERADDR|(p->pid&0xFFFF)))
panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va);
tlbvirt = USERADDR;
tlbphys = PPN(p->upage->pa) | PTEVALID | PTEKERNEL;
putkmmu(tlbvirt, tlbphys);
- flushmmu();
- u = (User*)USERADDR;
+
+ /*
+ * if not a kernel process and this process was not the
+ * last process on this machine, flush & preload mmu
+ */
+ if(!p->kp && p!=m->lproc){
+ flushmmu();
+
+ /*
+ * preload the MMU with the last (up to) NMMU user entries
+ * previously faulted into it for this process.
+ */
+ mn = &u->mc.mmu[u->mc.next&(NMMU-1)];
+ me = &u->mc.mmu[NMMU];
+ if(u->mc.next >= NMMU){
+ for(mm = mn; mm < me; mm++)
+ UMAP[mm->va] = mm->pa;
+ }
+ for(mm = u->mc.mmu; mm < mn; mm++)
+ UMAP[mm->va] = mm->pa;
+
+ m->lproc = p;
+ }
}
void
@@ 45,7 67,19 @@ putmmu(ulong tlbvirt, ulong tlbphys)
if(tlbvirt&KZERO)
panic("putmmu");
tlbphys |= VTAG(tlbvirt)<<24;
- UMAP[(tlbvirt&0x003FE000L)>>2] = tlbphys;
+ tlbvirt = (tlbvirt&0x003FE000L)>>2;
+ if(u){
+ MMU *mp;
+ int s;
+
+ s = splhi();
+ mp = &(u->mc.mmu[u->mc.next&(NMMU-1)]);
+ mp->pa = tlbphys;
+ mp->va = tlbvirt;
+ u->mc.next++;
+ splx(s);
+ }
+ UMAP[tlbvirt] = tlbphys;
}
void
@@ 57,6 91,14 @@ flushmmu(void)
}
void
+clearmmucache(void)
+{
+ if(u == 0)
+ panic("flushmmucache");
+ u->mc.next = 0;
+}
+
+void
kmapinit(void)
{
KMap *k;
M gnot/proc.c => gnot/proc.c +197 -108
@@ 43,91 43,206 @@ char *statename[]={ /* BUG: generate automatically */
"Broken",
};
+int page_alloc(int); /* !ORIG */
+void page_free(int, int);
+
/*
- * Always splhi()'ed.
+ * Called as the last routine in main(). Wait for a process on the run queue, grab it,
+ * and run it. Note that in this routine the interrupts are enabled for the first time.
*/
void
schedinit(void) /* never returns */
{
Proc *p;
+ /*
+ * At init time: wait for a process on the run queue.
+ */
+ for (;;) {
+ spllo();
+ while (runq.head == 0)
+ /* idle loop */;
+ splhi();
+ lock(&runq);
+ if (runq.head != 0)
+ break;
+ unlock(&runq);
+ }
+
+ /*
+ * Set the u pointer and leave it there. In fact, it might as well be a define.
+ */
+ u = (User *) USERADDR;
+
+ /*
+ * For later rescheduling. Jumped to by sched() on stack switch.
+ */
setlabel(&m->sched);
- if(u){
- m->proc = 0;
- p = u->p;
- putkmmu(USERADDR, INVALIDPTE); /* safety first */
- u = 0;
- if(p->state == Running)
- ready(p);
- else if(p->state == Moribund){
- p->pid = 0;
- unlock(&p->debug);
- p->upage->ref--;
- /* procalloc already locked */
- p->qnext = procalloc.free;
- procalloc.free = p;
- p->upage = 0;
- unlock(&procalloc);
- p->state = Dead;
- }
- p->mach = 0;
+
+ /*
+ * Take a process from the run queue. The run queue is locked here, and guaranteed
+ * to have a process on it.
+ */
+ p = runq.head;
+ if ((runq.head = p->rnext) == 0)
+ runq.tail = 0;
+ unlock(&runq);
+
+ /*
+ * Ok, here we go. We have a process and we can start running.
+ */
+ mapstack(p);
+ gotolabel(&p->sched);
+}
+
+/*
+ * Complete the restoring of a process after mapstack(). The interrupt level here is low.
+ * However, since the process is not Running, it cannot be rescheduled at this point. We
+ * set the process state to Running. If the previous process was dead, clean it up.
+ */
+void
+restore(void)
+{
+ Proc *p = m->proc; /* previous process */
+
+ u->p->mach = m;
+ m->proc = u->p;
+ u->p->state = Running;
+ if (p->state == Moribund) {
+ p->pid = 0;
+ unlock(&p->debug); /* set in pexit */
+ p->upage->ref--;
+ p->upage = 0;
+ p->qnext = procalloc.free;
+ procalloc.free = p;
+ unlock(&procalloc); /* set in pexit */
+ p->state = Dead;
}
- sched();
}
+/*
+ * Save part of the process state. Note: this is not the counterpart of restore().
+ */
+void
+save(Balu *balu)
+{
+ fpsave(&u->fpsave);
+ if (u->fpsave.type) {
+ if(u->fpsave.size > sizeof u->fpsave.junk)
+ panic("fpsize %d max %d\n", u->fpsave.size, sizeof u->fpsave.junk);
+ fpregsave(u->fpsave.reg);
+ u->p->fpstate = FPactive;
+ m->fpstate = FPdirty;
+ }
+ if (BALU->cr0 != 0xFFFFFFFF) /* balu busy */
+ memcpy(balu, BALU, sizeof *balu);
+ else {
+ balu->cr0 = 0xFFFFFFFF;
+ BALU->cr0 = 0xFFFFFFFF;
+ }
+}
+
+/*
+ * Reschedule the process. We do not know whether the interrupt level is low or high
+ * here, but we set it to low in any case. If there is no other process to run, and
+ * this process is Running, return immediately. If this process is blocked, and there
+ * is no other process to run, keep spinning until either this process or another
+ * process becomes runnable. If it was this process, we can return immediately.
+ */
void
sched(void)
{
- Proc *p;
- ulong tlbvirt, tlbphys;
+ Proc *p = u->p;
+ long initfp;
Balu balu;
+ int saved = 0;
- if(u){
- splhi();
+ /*
+ * Record that the process is spinning instead of blocked. Ready() uses this
+ * information to decide what to do with the process.
+ */
+ p->spin = 1;
- fpsave(&u->fpsave);
- if(u->fpsave.type){
- if(u->fpsave.size > sizeof u->fpsave.junk)
- panic("fpsize %d max %d\n", u->fpsave.size, sizeof u->fpsave.junk);
- fpregsave(u->fpsave.reg);
- u->p->fpstate = FPactive;
- m->fpstate = FPdirty;
- }
- if(BALU->cr0 != 0xFFFFFFFF) /* balu busy */
- memcpy(&balu, BALU, sizeof balu);
- else{
- balu.cr0 = 0xFFFFFFFF;
- BALU->cr0 = 0xFFFFFFFF;
- }
- if(setlabel(&u->p->sched)){ /* woke up */
-if(u->p->mach)panic("mach non zero");
- p = u->p;
- p->state = Running;
- p->mach = m;
- m->proc = p;
- if(p->fpstate != m->fpstate){
- if(p->fpstate == FPinit){
- u->p->fpstate = FPinit;
- fprestore(&initfp);
- m->fpstate = FPinit;
- }else{
- fpregrestore(u->fpsave.reg);
- fprestore(&u->fpsave);
- m->fpstate = FPdirty;
- }
+ /*
+ * Look for a new process to be run.
+ */
+ for (;;) {
+ spllo();
+
+ /*
+ * Idle loop. Return when this process becomes runnable. If nothing else
+ * to do, start saving some of the process state.
+ */
+ while (runq.head == 0)
+ if (p->state == Running)
+ return;
+ else if (!saved) {
+ save(&balu);
+ saved = 1;
}
- if(balu.cr0 != 0xFFFFFFFF) /* balu busy */
- memcpy(BALU, &balu, sizeof balu);
- spllo();
- return;
- }
- gotolabel(&m->sched);
+
+ /*
+ * Disable clock interrupts so that there will be no rescheduling in this
+ * section (on this machine). If there is still a process on the run
+ * queue, break out of this loop.
+ */
+ splhi();
+ lock(&runq);
+ if (runq.head != 0)
+ break;
+ unlock(&runq);
+ }
+ p->spin = 0;
+
+ /*
+ * The first process on the run queue is the process we are going to run. First
+ * save our state before we jump to schedinit. If this process was running, put
+ * it on the run queue.
+ */
+ if (p->state == Running) {
+ p->state = Ready;
+ p->rnext = 0;
+ runq.tail->rnext = p;
+ runq.tail = p;
}
+
+ /*
+ * Save some process state (if we haven't done that already) and save/restore
+ * pc and sp. We have to jump to schedinit() because we are going to remap the
+ * stack.
+ */
+ if (!saved)
+ save(&balu);
+ if (setlabel(&p->sched) == 0)
+ gotolabel(&m->sched);
+
+ /*
+ * Interrupts are ok now. Note that the process state is still not Running,
+ * so no rescheduling.
+ */
spllo();
- p = runproc();
- splhi();
- mapstack(p);
- gotolabel(&p->sched);
+
+ /*
+ * Jumped to by schedinit. Restore the process state.
+ */
+ if (p->fpstate != m->fpstate)
+ if (p->fpstate == FPinit) {
+ initfp = 0;
+ fprestore((FPsave *) &initfp);
+ m->fpstate = FPinit;
+ }
+ else {
+ fpregrestore(u->fpsave.reg);
+ fprestore(&u->fpsave);
+ m->fpstate = FPdirty;
+ }
+ if (balu.cr0 != 0xFFFFFFFF) /* balu busy */
+ memcpy(BALU, &balu, sizeof balu);
+
+ /*
+ * Complete restoring the process.
+ */
+ restore();
}
void
@@ 135,6 250,10 @@ ready(Proc *p)
{
int s;
+ if (p->spin) {
+ p->state = Running;
+ return;
+ }
s = splhi();
lock(&runq);
p->rnext = 0;
@@ 148,42 267,6 @@ ready(Proc *p)
splx(s);
}
-void
-checksched(void) /* just for efficiency; don't sched if no need */
-{
- if(runq.head)
- sched();
-}
-
-/*
- * Always called spllo
- */
-Proc*
-runproc(void)
-{
- Proc *p;
-
-loop:
- do; while(runq.head == 0);
- splhi();
- lock(&runq);
- p = runq.head;
- if(p==0 || p->mach){ /* p->mach==0 only when process state is saved */
- unlock(&runq);
- spllo();
- goto loop;
- }
- if(p->rnext == 0)
- runq.tail = 0;
- runq.head = p->rnext;
- if(p->state != Ready)
- print("runproc %s %d %s\n", p->text, p->pid, statename[p->state]);
- unlock(&runq);
- p->state = Scheding;
- spllo();
- return p;
-}
-
Proc*
newproc(void)
{
@@ 204,6 287,7 @@ loop:
p->child = 0;
p->exiting = 0;
p->fpstate = FPinit;
+ p->kp = 0;
memset(p->seg, 0, sizeof p->seg);
lock(&pidalloc);
p->pid = ++pidalloc.pid;
@@ 530,6 614,12 @@ pexit(char *s, int freemem)
lock(&procalloc); /* sched() can't do this */
lock(&c->debug); /* sched() can't do this */
c->state = Moribund;
+
+ /*
+ * Call the scheduler. This process gets cleaned up in restore() by the next
+ * process that runs. That means that if there is no other process, we'll
+ * hang around for a little while.
+ */
sched(); /* never returns */
}
@@ 582,7 672,8 @@ proctab(int i)
}
#include <ureg.h>
-DEBUG()
+void
+DEBUG(void)
{
int i;
Proc *p;
@@ 612,15 703,16 @@ kproc(char *name, void (*func)(void *), void *arg)
* Kernel stack
*/
p = newproc();
+ p->kp = 1;
p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF));
k = kmap(p->upage);
upa = VA(k);
up = (User*)upa;
- up->p = p;
/*
* Save time: only copy u-> data and useful stack
*/
+ clearmmucache();
memcpy(up, u, sizeof(User));
n = USERADDR+BY2PG - (ulong)&lastvar;
n = (n+32) & ~(BY2WD-1); /* be safe & word align */
@@ 633,17 725,14 @@ kproc(char *name, void (*func)(void *), void *arg)
for(n=0; n<=up->maxfd; n++)
up->fd[n] = 0;
up->maxfd = 0;
+ up->p = p;
kunmap(k);
/*
* Sched
*/
if(setlabel(&p->sched)){
- u->p = p;
- p->state = Running;
- p->mach = m;
- m->proc = p;
- spllo();
+ restore();
(*func)(arg);
pexit(0, 1);
}
M gnot/screen.c => gnot/screen.c +5 -2
@@ 24,6 24,8 @@ void duartinit(void);
int duartacr;
int duartimr;
+void (*kprofp)(ulong);
+
GBitmap gscreen =
{
(ulong*)((4*1024*1024-256*1024)|KZERO), /* BUG */
@@ 287,7 289,7 @@ duartbreak(int ms)
}
enum{
- Kptime=200 /* about once per ms */
+ Kptime=200
};
void
duartstarttimer(void)
@@ 349,7 351,8 @@ duartintr(Ureg *ur)
* Is it 0?
*/
if(cause & IM_CRDY){
-/* kproftimer(ur->pc);/**/
+ if(kprofp)
+ (*kprofp)(ur->pc);
c = duart[1].scc_ropbc;
duart[0].ctur = (Kptime)>>8;
duart[0].ctlr = (Kptime)&255;
M gnot/sturp.c => gnot/sturp.c +14 -8
@@ 11,7 11,7 @@ enum {
Nmask= 0x7,
};
-#define DPRINT if(q->flag&QDEBUG)kprint
+#define DPRINT if(q->flag&QDEBUG)print
typedef struct Urp Urp;
@@ 33,7 33,7 @@ struct urpstat {
} urpstat;
struct Urp {
- QLock;
+ Lock;
short state; /* flags */
Rendez r; /* process waiting for close */
@@ 140,10 140,10 @@ urpopen(Queue *q, Stream *s)
* find a free urp structure
*/
for(up = urp; up < &urp[conf.nurp]; up++){
- qlock(up);
+ lock(up);
if(up->state == 0)
break;
- qunlock(up);
+ unlock(up);
}
if(up == &urp[conf.nurp]){
q->ptr = 0;
@@ 155,7 155,7 @@ urpopen(Queue *q, Stream *s)
up->rq = q;
up->wq = q->other;
up->state = OPEN;
- qunlock(up);
+ unlock(up);
initinput(up, 0);
initoutput(up, 0);
@@ 236,7 236,10 @@ urpclose(Queue *q)
while(up->kstarted)
sleep(&up->r, isdead, up);
+ lock(up);
up->state = 0;
+ up->rq = 0;
+ unlock(up);
}
/*
@@ 990,15 993,18 @@ urptimer(Alarm *a)
{
Urp *up;
Urp *last;
- Queue *q;
cancel(a);
alarm(500, urptimer, 0);
for(up = urp, last = &urp[conf.nurp]; up < last; up++){
if(up->state==0)
continue;
- if(up->rq && todo(up))
- wakeup(&up->rq->r);
+ if(up->rq && canlock(up)){
+ if(up->rq && NOW>up->timer
+ && ((up->state&INITING) || up->unechoed!=up->next))
+ wakeup(&up->rq->r);
+ unlock(up);
+ }
}
}
M gnot/sysproc.c => gnot/sysproc.c +5 -5
@@ 41,6 41,7 @@ sysfork(ulong *arg)
/*
* Save time: only copy u-> data and useful stack
*/
+ clearmmucache();
memcpy((void*)upa, u, sizeof(User));
n = USERADDR+BY2PG - (ulong)&lastvar;
n = (n+32) & ~(BY2WD-1); /* be safe & word align */
@@ 128,11 129,8 @@ sysfork(ulong *arg)
* Sched
*/
if(setlabel(&p->sched)){
- u->p = p;
- p->state = Running;
- p->mach = m;
- m->proc = p;
- spllo();
+ clearmmucache();
+ restore();
return 0;
}
p->pop = u->p;
@@ 147,6 145,7 @@ sysfork(ulong *arg)
memcpy(p->text, u->p->text, NAMELEN);
ready(p);
flushmmu();
+ clearmmucache();
return pid;
}
@@ 361,6 360,7 @@ sysexec(ulong *arg)
unlock(o);
flushmmu();
+ clearmmucache();
((Ureg*)UREGADDR)->pc = exec.entry;
sp = (ulong*)(USTKTOP - ssize);
*--sp = nargs;
M port/devdk.c => port/devdk.c +8 -10
@@ 499,6 499,14 @@ dkmuxconfig(Dk *dp, Block *bp)
dp->csc = c;
/*
+ * tell datakit we've rebooted. It should close all channels.
+ */
+ if(dp->restart) {
+ DPRINT("dkmuxconfig: restart %s\n", dp->name);
+ dkmesg(dp, T_ALIVE, D_RESTART, 0, 0);
+ }
+
+ /*
* start a process to deal with it
*/
sprint(buf, "csc.%s.%d", dp->name, dp->ncsc);
@@ 1316,16 1324,6 @@ dkcsckproc(void *a)
dp = (Dk *)a;
/*
- * tell datakit we've rebooted. It should close all channels.
- */
- if(dp->restart) {
- DPRINT("dkcsckproc: restart %s\n", dp->name);
- dkmesg(dp, T_ALIVE, D_RESTART, 0, 0);
- }
- DPRINT("dkcsckproc: closeall %s\n", dp->name);
- dkmesg(dp, T_CHG, D_CLOSEALL, 0, 0);
-
- /*
* loop forever listening
*/
for(;;){
M port/devkprof.c => port/devkprof.c +9 -1
@@ 30,9 30,12 @@ Dirtab kproftab[Nkproftab]={
"kpstop", Kprofstopqid, 0, 0600,
};
+void kproftimer(ulong);
+
void
kprofreset(void)
{
+ kprofp = kproftimer;
}
void
@@ 157,7 160,12 @@ kprofwrite(Chan *c, char *a, long n)
void
kproftimer(ulong pc)
{
- extern ulong splpc;
+ /*
+ * if the pc is coming out of slplo pr splx, then use
+ * the pc saved when we went splhi.
+ */
+ if(pc>=(ulong)spllo && pc<=(ulong)spldone)
+ pc = m->splpc;
timerbuf[0]++;
if(KTZERO<=pc && pc<KTZERO+MAXPC){
M port/devmnt.c => port/devmnt.c +1 -4
@@ 747,11 747,8 @@ mntxmit(Mnt *m, Mnthdr *mh)
/*
* Copy out on read
*/
- if(mh->thdr.type == Tread){
- if(mh->rhdr.count>497 && mh->rhdr.data[497]==011)
- print("*497==11 %lux\n", &mh->rhdr.data[497]);
+ if(mh->thdr.type == Tread)
memcpy(mh->thdr.data, mh->rhdr.data, mh->rhdr.count);
- }
mbfree(mh->mbr);
mbfree(mbw);
poperror();
M port/sturp.c => port/sturp.c +27 -14
@@ 33,7 33,7 @@ struct urpstat {
} urpstat;
struct Urp {
- QLock;
+ Lock;
short state; /* flags */
Rendez r; /* process waiting for close */
@@ 140,10 140,10 @@ urpopen(Queue *q, Stream *s)
* find a free urp structure
*/
for(up = urp; up < &urp[conf.nurp]; up++){
- qlock(up);
+ lock(up);
if(up->state == 0)
break;
- qunlock(up);
+ unlock(up);
}
if(up == &urp[conf.nurp]){
q->ptr = 0;
@@ 155,7 155,7 @@ urpopen(Queue *q, Stream *s)
up->rq = q;
up->wq = q->other;
up->state = OPEN;
- qunlock(up);
+ unlock(up);
initinput(up, 0);
initoutput(up, 0);
@@ 236,7 236,10 @@ urpclose(Queue *q)
while(up->kstarted)
sleep(&up->r, isdead, up);
+ lock(up);
up->state = 0;
+ up->rq = 0;
+ unlock(up);
}
/*
@@ 465,6 468,7 @@ urpiput(Queue *q, Block *bp)
case ACK+4: case ACK+5: case ACK+6: case ACK+7:
case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3:
case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7:
+ DPRINT("rACK %ux\n", ctl);
rcvack(up, ctl);
break;
@@ 695,15 699,18 @@ static void
sendctl(Urp *up, int ctl)
{
Block *bp;
+ Queue *q;
- if(QFULL(up->wq->next))
+ q = up->wq;
+ if(QFULL(q->next))
return;
bp = allocb(1);
bp->wptr = bp->lim;
bp->rptr = bp->lim-1;
*bp->rptr = ctl;
bp->flags |= S_DELIM;
- PUTNEXT(up->wq, bp);
+ PUTNEXT(q, bp);
+ DPRINT("sCTL %ulx\n", ctl);
}
/*
@@ 762,9 769,11 @@ sendblock(Urp *up, int bn)
{
Block *bp, *m, *nbp;
int n;
+ Queue *q;
+ q = up->wq;
up->timer = NOW + MSrexmit;
- if(QFULL(up->wq->next))
+ if(QFULL(q->next))
return;
/*
@@ 781,7 790,7 @@ sendblock(Urp *up, int bn)
nbp->rptr = bp->rptr;
nbp->wptr = bp->wptr;
nbp->flags |= S_DELIM;
- PUTNEXT(up->wq, m);
+ PUTNEXT(q, m);
/*
* message 2, the block length and the SEQ
@@ 794,7 803,8 @@ sendblock(Urp *up, int bn)
m->rptr[1] = n;
m->rptr[2] = n<<8;
m->flags |= S_DELIM;
- PUTNEXT(up->wq, m);
+ PUTNEXT(q, m);
+ DPRINT("sb %d\n", bn);
}
/*
@@ 945,8 955,8 @@ todo(void *arg)
return (up->state&INITING)
? NOW>up->timer /* time to INIT1 */
: ((up->unechoed!=up->next && NOW>up->timer) /* time to ENQ */
- || WINDOW(up)>0 && up->next!=up->nxb
- || (!QFULL(up->rq->next) && up->iseq!=(up->lastecho&7))); /* time to ECHO */
+ || (WINDOW(up)>0 && (up->next!=up->nxb || up->wq->first)) /* open xmit window */
+ || (up->iseq!=(up->lastecho&7) && !QFULL(up->rq->next))); /* time to ECHO */
}
static void
urpkproc(void *arg)
@@ 983,15 993,18 @@ urptimer(Alarm *a)
{
Urp *up;
Urp *last;
- Queue *q;
cancel(a);
alarm(500, urptimer, 0);
for(up = urp, last = &urp[conf.nurp]; up < last; up++){
if(up->state==0)
continue;
- if(up->rq && todo(up))
- wakeup(&up->rq->r);
+ if(up->rq && canlock(up)){
+ if(up->rq && NOW>up->timer
+ && ((up->state&INITING) || up->unechoed!=up->next))
+ wakeup(&up->rq->r);
+ unlock(up);
+ }
}
}
M port/sysfile.c => port/sysfile.c +1 -1
@@ 181,7 181,7 @@ sysread(ulong *arg)
long n;
c = fdtochan(arg[0], 0);
- validaddr(arg[1], arg[2], 0);
+ validaddr(arg[1], arg[2], 1);
qlock(c);
if(waserror()){
qunlock(c);
M power/main.c => power/main.c +1 -2
@@ 121,7 121,6 @@ ioboardinit(void)
maxlevel = 8;
noforce = 0;
}
- print("IO %d\n", ioid);
/*
* reset VME bus (MODEREG is on the IO2)
@@ 590,7 589,7 @@ confinit(void)
/*
* set minimal default values
*/
- conf.nmach = 1;
+ conf.nmach = 2;
conf.nmod = 2000;
conf.nalarm = 10000;
conf.norig = 500;