M port/devcons.c => port/devcons.c +1 -0
@@ 233,6 233,7 @@ echo(Rune r, char *buf, int n)
xsummary();
ixsummary();
poolsummary();
+ pagersummary();
break;
case 'd':
if(consdebug != nil)
M port/fault.c => port/fault.c +39 -52
@@ 95,13 95,9 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
lkp = *pg;
lock(lkp);
- /* uncache the current swap image (since we may be changing it) */
- if(lkp->image){
- if(lkp->image == &swapimage)
- uncachepage(lkp);
- else
- duppage(lkp);
- }
+ /* save a copy of the original for the image cache */
+ if(lkp->image)
+ duppage(lkp);
unlock(lkp);
goto done;
@@ 153,16 149,9 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
putpage(lkp);
}
else {
- /* uncache the current page (since we may be changing it)
- * and, if a text page, put a duplicate back onto
- * the free list
- */
- if(lkp->image){
- if(lkp->image == &swapimage)
- uncachepage(lkp);
- else
- duppage(lkp);
- }
+ /* save a copy of the original for the image cache */
+ if(lkp->image)
+ duppage(lkp);
unlock(lkp);
}
@@ 200,7 189,7 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
void
pio(Segment *s, ulong addr, ulong soff, Page **p)
{
- Page *new, *new2;
+ Page *new;
KMap *k;
Chan *c;
int n, ask;
@@ 208,22 197,26 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
ulong daddr;
Page *loadrec;
+retry:
loadrec = *p;
if(loadrec == 0) { /* from a text/data image */
daddr = s->fstart+soff;
new = lookpage(s->image, daddr);
+ if(new != nil) {
+ *p = new;
+ return;
+ }
}
else { /* from a swap image */
daddr = swapaddr(loadrec);
new = lookpage(&swapimage, daddr);
- if(new != nil)
+ if(new != nil) {
putswap(loadrec);
+ *p = new;
+ return;
+ }
}
- if(new != nil) { /* Page found from cache */
- *p = new;
- return;
- }
qunlock(&s->lk);
@@ 254,7 247,11 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
poperror();
kunmap(k);
qlock(&s->lk);
- /* race, we may have multiple simultaneous reads */
+
+ /*
+ * race, another proc may have gotten here first while
+ * s->lk was unlocked
+ */
if(*p == 0) {
new->daddr = daddr;
cachepage(new, s->image);
@@ 265,35 262,9 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
}
else { /* This is paged out */
c = swapimage.c;
- qlock(&swapimage.rdlock); /* mutex */
-
- /*
- * multiple processes could be swapping in the
- * same page for the same segment
- */
- if(!pagedout(*p)){
- putpage(new);
- qunlock(&swapimage.rdlock);
- goto done;
- }
-
- /*
- * multiple processes could be swapping in the
- * same page for different segments
- */
- new2 = lookpage(&swapimage, daddr);
- if(new2 != nil){
- putpage(new);
- *p = new2;
- putswap(loadrec);
- qunlock(&swapimage.rdlock);
- goto done;
- }
-
if(waserror()) {
kunmap(k);
putpage(new);
- qunlock(&swapimage.rdlock);
qlock(&s->lk);
qunlock(&s->lk);
faulterror("sys: page in I/O error");
@@ 307,12 278,28 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
kunmap(k);
qlock(&s->lk);
+ /*
+ * race, another proc may have gotten here first
+ * (and the pager may have run on that page) while
+ * s->lk was unlocked
+ */
+ if(*p != loadrec){
+ if(!pagedout(*p)){
+ /* another process did it for me */
+ putpage(new);
+ goto done;
+ } else {
+print("!");
+ /* another process and the pager got in */
+ putpage(new);
+ goto retry;
+ }
+ }
+
new->daddr = daddr;
cachepage(new, &swapimage);
*p = new;
putswap(loadrec);
-
- qunlock(&swapimage.rdlock);
}
done:
M port/portdat.h => port/portdat.h +1 -1
@@ 326,7 326,6 @@ struct Image
Image *hash; /* Qid hash chains */
Image *next; /* Free list */
int notext; /* no file associated */
- QLock rdlock; /* mutex for reading from image */
};
struct Pte
@@ 622,6 621,7 @@ struct Proc
int preempted; /* true if this process hasn't finished the interrupt
* that last preempted it
*/
+ ulong qpc; /* pc calling last blocking qlock */
void *ureg; /* User registers for notes */
void *dbgreg; /* User registers for devproc */
M port/portfns.h => port/portfns.h +1 -0
@@ 174,6 174,7 @@ Block* packblock(Block*);
Block* padblock(Block*, int);
void pagechainhead(Page*);
void pageinit(void);
+void pagersummary(void);
void panic(char*, ...);
int parseether(uchar*, char*);
int parsefields(char*, char**, int, char*);
M port/proc.c => port/proc.c +2 -2
@@ 903,9 903,9 @@ dumpaproc(Proc *p)
s = p->psstate;
if(s == 0)
s = "kproc";
- print("%3lud:%10s pc %8lux dbgpc %8lux %8s (%s) ut %ld st %ld bss %lux pri %lud\n",
+ print("%3lud:%10s pc %8lux dbgpc %8lux %8s (%s) ut %ld st %ld bss %lux qpc %lux\n",
p->pid, p->text, p->pc, dbgpc(p), s, statename[p->state],
- p->time[0], p->time[1], bss, p->priority);
+ p->time[0], p->time[1], bss, p->qpc);
}
void
M port/qlock.c => port/qlock.c +1 -0
@@ 35,6 35,7 @@ rwstats.qlockq++;
q->tail = mp;
mp->qnext = 0;
mp->state = Queueing;
+ up->qpc = getcallerpc(q);
unlock(&q->use);
sched();
}
M port/swap.c => port/swap.c +19 -14
@@ 124,7 124,9 @@ loop:
if(p->state == Dead || p->kp)
continue;
- qlock(&p->seglock);
+ if(!canqlock(&p->seglock))
+ continue; /* process changing its segments */
+
for(i = 0; i < NSEG; i++) {
if(!needpages(junk)){
qunlock(&p->seglock);
@@ 278,19 280,6 @@ pagepte(int type, Page **pg)
case SG_SHARED:
case SG_SHDATA:
case SG_MAP:
- /* if it's already on disk, no need to do io again */
-#ifdef asdf
- lock(outp);
- if(outp->image == &swapimage){
- dupswap((Page*)outp->daddr);
- *pg = (Page*)(outp->daddr|PG_ONSWAP);
- unlock(outp);
- putpage(outp);
- return;
- }
- unlock(outp);
-#endif asdf
-
/*
* get a new swap address and clear any pages
* referring to it from the cache
@@ 312,6 301,7 @@ pagepte(int type, Page **pg)
/*
* enter it into the cache so that a fault happening
* during the write will grab the page from the cache
+ * rather than one partially written to the disk
*/
outp->daddr = daddr;
cachepage(outp, &swapimage);
@@ 324,6 314,15 @@ pagepte(int type, Page **pg)
}
}
+void
+pagersummary(void)
+{
+ print("%lud/%lud memory %lud/%lud swap %d iolist\n",
+ palloc.user-palloc.freecount,
+ palloc.user, conf.nswap-swapalloc.free, conf.nswap,
+ ioptr);
+}
+
static void
executeio(void)
{
@@ 336,13 335,17 @@ executeio(void)
c = swapimage.c;
for(i = 0; i < ioptr; i++) {
+ if(ioptr > conf.nswppo)
+ panic("executeio: ioptr %d > %d\n", ioptr, conf.nswppo);
out = iolist[i];
+ up->psstate = "I/Okm";
k = kmap(out);
kaddr = (char*)VA(k);
if(waserror())
panic("executeio: page out I/O error");
+ up->psstate = "I/Owr";
n = devtab[c->type]->write(c, kaddr, BY2PG, out->daddr);
if(n != BY2PG)
nexterror();
@@ 351,9 354,11 @@ executeio(void)
poperror();
/* Free up the page after I/O */
+ up->psstate = "I/Odec";
lock(out);
out->ref--;
unlock(out);
+ up->psstate = "I/Oput";
putpage(out);
}
ioptr = 0;