~kris/9p

9hist

edd4dbfa92556a4498704ac0942a8eaee431dc58 — David du Colombier 27 years ago a7cce8b
Plan 9 from Bell Labs 1999-01-09
3 files changed, 80 insertions(+), 44 deletions(-)

M port/fault.c
M port/page.c
M port/swap.c
M port/fault.c => port/fault.c +45 -22
@@ 17,7 17,7 @@ fault(ulong addr, int read)

	m->pfault++;
	for(;;) {
		s = seg(up, addr, 1);
		s = seg(up, addr, 1);		/* leaves s->lk qlocked if seg != nil */
		if(s == 0) {
			up->psstate = sps;
			return -1;


@@ 88,18 88,21 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
		break;

	case SG_SHDATA:			/* Shared data */
	shared:
		if(pagedout(*pg))
			pio(s, addr, soff, pg);

		lkp = *pg;
		lock(lkp);

		/* 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)
			duppage(lkp);
		/* uncache the current swap image (since we may be changing it) */
		if(lkp->image){
			if(lkp->image == &swapimage)
				uncachepage(lkp);
			else
				duppage(lkp);
		}

		unlock(lkp);
		goto done;



@@ 118,15 121,16 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)

			*pg = new;
		}
		/* NO break */
		if(type == SG_SHARED)
			goto shared;

	case SG_DATA:			/* Demand load/pagein/copy on write */
		goto notshared;

	case SG_DATA:
	notshared:			/* Demand load/pagein/copy on write */
		if(pagedout(*pg))
			pio(s, addr, soff, pg);

		if(type == SG_SHARED)
			goto done;

		if(read && conf.copymode == 0) {
			mmuphys = PPN((*pg)->pa)|PTERONLY|PTEVALID;
			(*pg)->modref |= PG_REF;


@@ 135,7 139,7 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)

		lkp = *pg;
		lock(lkp);
		if(lkp->image == &swapimage && lkp->daddr)
		if(lkp->image == &swapimage)
			ref = lkp->ref + swapcount(lkp->daddr);
		else
			ref = lkp->ref;


@@ 153,8 157,12 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
			 * and, if a text page, put a duplicate back onto
			 * the free list
			 */
			if(lkp->image)
				duppage(lkp);
			if(lkp->image){
				if(lkp->image == &swapimage)
					uncachepage(lkp);
				else
					duppage(lkp);
			}

			unlock(lkp);
		}


@@ 201,18 209,18 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
	Page *loadrec;

	loadrec = *p;
	if(loadrec == 0) {
		daddr = s->fstart+soff;		/* Compute disc address */
	if(loadrec == 0) {	/* from a text/data image */
		daddr = s->fstart+soff;
		new = lookpage(s->image, daddr);
	}
	else {
	else {			/* from a swap image */
		daddr = swapaddr(loadrec);
		new = lookpage(&swapimage, daddr);
		if(new != nil)
			putswap(loadrec);
	}

	if(new) {				/* Page found from cache */
	if(new != nil) {			/* Page found from cache */
		*p = new;
		return;
	}


@@ 259,13 267,27 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
		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);
			putswap(*p);
			*p = new2;
			putswap(loadrec);
			qunlock(&swapimage.rdlock);
			return;
			goto done;
		}

		if(waserror()) {


@@ 286,13 308,14 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
		qlock(&s->lk);

		new->daddr = daddr;
		putswap(*p);
		cachepage(new, &swapimage);
		*p = new;
		putswap(loadrec);

		qunlock(&swapimage.rdlock);
	}

done:
	if(s->flushme)
		memset((*p)->cachectl, PG_TXTFLUSH, sizeof((*p)->cachectl));
}

M port/page.c => port/page.c +13 -11
@@ 215,6 215,10 @@ putpage(Page *p)

	lock(&palloc);
	lock(p);

	if(p->ref == 0)
		panic("putpage");

	if(--p->ref > 0) {
		unlock(p);
		unlock(&palloc);


@@ 271,15 275,9 @@ retry:
		panic("duppage %d", retries);

	/* don't dup pages with no image */
	if(p->ref == 0 || p->image == nil)
	if(p->ref == 0 || p->image == nil || p->image->notext)
		return;

	/* No dup for swap/cache pages but we still have to uncache */
	if(p->image->notext){
		uncachepage(p);
		return;
	}

	/*
	 *  normal lock ordering is to call
	 *  lock(&palloc) before lock(p).


@@ 395,10 393,14 @@ cachedel(Image *i, ulong daddr)
	l = &pghash(daddr);
	for(f = *l; f; f = f->hash) {
		if(f->image == i && f->daddr == daddr) {
			*l = f->hash;
			putimage(f->image);
			f->image = 0;
			f->daddr = 0;
			lock(f);
			if(f->image == i && f->daddr == daddr){
				*l = f->hash;
				putimage(f->image);
				f->image = 0;
				f->daddr = 0;
			}
			unlock(f);
			break;
		}
		l = &f->hash;

M port/swap.c => port/swap.c +22 -11
@@ 60,12 60,12 @@ putswap(Page *p)
	lock(&swapalloc);
	idx = &swapalloc.swmap[((ulong)p)/BY2PG];
	if(--(*idx) == 0) {
		if(swapalloc.swmap[((ulong)p)/BY2PG]==255)
			panic("putswap");
		swapalloc.free++;
		if(idx < swapalloc.last)
			swapalloc.last = idx;
	}
	if(*idx >= 254)
		panic("putswap %lux == %ud", p, *idx);
	unlock(&swapalloc);
}



@@ 73,9 73,8 @@ void
dupswap(Page *p)
{
	lock(&swapalloc);
	if(swapalloc.swmap[((ulong)p)/BY2PG]==255)
	if(++swapalloc.swmap[((ulong)p)/BY2PG] == 0)
		panic("dupswap");
	swapalloc.swmap[((ulong)p)/BY2PG]++;
	unlock(&swapalloc);
}



@@ 279,10 278,10 @@ pagepte(int type, Page **pg)
	case SG_SHARED:
	case SG_SHDATA:
	case SG_MAP:
		/* if it's already on disk, we're done */
		/* if it's already on disk, no need to do io again */
#ifdef asdf
		lock(outp);
		if(outp->daddr != 0 && outp->image == &swapimage){
		if(outp->image == &swapimage){
			dupswap((Page*)outp->daddr);
			*pg = (Page*)(outp->daddr|PG_ONSWAP);
			unlock(outp);


@@ 292,22 291,34 @@ pagepte(int type, Page **pg)
		unlock(outp);
#endif asdf

		/*
		 *  get a new swap address and clear any pages
		 *  referring to it from the cache
		 */
		daddr = newswap();
		cachedel(&swapimage, daddr);

		lock(outp);
		outp->ref++;

		/* forget anything that it used to cache */
		uncachepage(outp);

		/* Enter swap page into cache before segment is unlocked so that
		 * a fault will cause a cache recovery rather than a pagein on a
		 * partially written block.
		/*
		 *  incr the reference count to make sure it sticks around while
		 *  being written
		 */
		outp->ref++;

		/*
		 *  enter it into the cache so that a fault happening
		 *  during the write will grab the page from the cache
		 */
		outp->daddr = daddr;
		cachepage(outp, &swapimage);
		*pg = (Page*)(daddr|PG_ONSWAP);
		unlock(outp);

		/* Add me to IO transaction list */
		/* Add page to IO transaction list */
		iolist[ioptr++] = outp;
		break;
	}