Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/page.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/page.c 1990/0227
## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/page.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"ureg.h"

struct
{
	Lock;
	ulong	addr;
	int	active;
	Page	*page;		/* base of Page structures, indexed by phys addr */
	ulong	minppn;		/* index of first usable page */
	Page	*head;		/* most recently used */
	Page	*tail;		/* least recently used */
}palloc;

struct
{
	Lock;
	Orig	*arena;
	Orig	*free;
}origalloc;

typedef union PTEA	PTEA;
union PTEA{
	PTE;
	struct{
		ulong	n;	/* for growpte */
		Orig	*o;	/* for growpte */
		PTEA	*next;	/* for newmod */
	};
};

struct
{
	Lock;
	PTEA	*arena;
	PTEA	*free;
	PTEA	*end;
}ptealloc;

struct{
	Lock;
	PTEA	*free;
}modalloc;

/*
 * Called to allocate permanent data structures, before calling pageinit().
 */
void*
ialloc(ulong n, int align)
{
	ulong p;

	if(palloc.active)
		print("ialloc bad\n");
	if(palloc.addr == 0)
		palloc.addr = ((ulong)&end)&~KZERO;
	if(align){
		palloc.addr += BY2PG-1;
		palloc.addr &= ~(BY2PG-1);
	}
	memset((void*)(palloc.addr|KZERO), 0, n);
	p = palloc.addr;
	palloc.addr += n;
	if(align){
		palloc.addr += BY2PG-1;
		palloc.addr &= ~(BY2PG-1);
	}
	return (void*)(p|KZERO);
}

void
audit(char *s)
{
	int nf, nb;
	Page *p;

static int here;
do;while(here);
here=1;

	p = palloc.head;
	nf=nb=0;
	while(p){
print("%lux %lux %d\n", p->pa, p->va, p->ref);
if(p->o) print("\t%d %lux %c\n", p->o->nproc, p->o->qid, devchar[p->o->type]);
delay(100);
		nf++;
		p = p->next;
	}
	p = palloc.tail;
	while(p){
		nb++;
		p = p->prev;
	}
	print("%s: nf: %d nb: %d\n", s, nf, nb);
	delay(1000);
here=0;
}

void
pageinit(void)
{
	ulong pa, nb, ppn;
	ulong i;
	Page *p;
	PTEA *pte;
	Orig *o;

	ptealloc.arena = ialloc(conf.npte*sizeof(PTEA), 0);
	ptealloc.free = ptealloc.arena;
	ptealloc.end = ptealloc.arena+conf.npte;

	modalloc.free = ialloc(conf.nmod*sizeof(PTEA), 0);

	pte = modalloc.free;
	for(i=0; i<conf.nmod-1; i++,pte++)
		pte->next = pte+1;
	pte->next = 0;

	origalloc.free = ialloc(conf.norig*sizeof(Orig), 0);
	origalloc.arena = origalloc.free;

	o = origalloc.free;
	for(i=0; i<conf.norig-1; i++,o++)
		o->next = o+1;
	o->next = 0;
	palloc.active = 1;

	nb = (conf.npage<<PGSHIFT) - palloc.addr;
	nb -= ((nb+(BY2PG-1))>>PGSHIFT)*sizeof(Page);	/* safe overestimate */
	nb &= ~(BY2PG-1);
	pa = (conf.npage<<PGSHIFT) - nb;	/* physical addr of first free page */
	ppn = pa >> PGSHIFT;			/* physical page number of first free page */
	palloc.page = (Page *)((palloc.addr - ppn*sizeof(Page))|KZERO);
	/*
	 * Now palloc.page[ppn] describes first free page
	 */
	palloc.minppn = ppn;
	palloc.addr = ppn<<PGSHIFT;

	palloc.head = &palloc.page[ppn];
	palloc.tail = &palloc.page[conf.npage-1];
	memset(palloc.head, 0, (conf.npage-ppn)*sizeof(Page));
	print("%lud free pages\n", conf.npage-ppn);
	for(p=palloc.head; p<=palloc.tail; p++,ppn++){
		p->next = p+1;
		p->prev = p-1;
		p->pa = ppn<<PGSHIFT;
	}
	palloc.head->prev = 0;
	palloc.tail->next = 0;
}

Page*
newpage(int noclear, Orig *o, ulong va)
{
	Page *p;
	Orig *o1;

	if(palloc.active == 0)
		print("newpage inactive\n");
loop:
	lock(&palloc);
	for(p=palloc.tail; p; p=p->prev){
		if(p->ref == 0)
			goto out;
#ifdef asdf
		if(p->ref == 1){	/* a pageout daemon should do this */
			o1 = p->o;
			if(o1 && o1->nproc==0 && canlock(o1)){
				if(o1->nproc){
					unlock(o1);
					continue;
				}
				print("free %d pages va %lux %lux %c\n", o1->npage, o->va, o1->qid, devchar[o1->type]);
				freepage(o1);
				/* neworig will free the orig and pte's later */
				unlock(o1);
				if(p->ref == 0)
					goto out;
				print("newpage ref != 0");
			}
		}
#endif
	}
	audit("newpage");
	print("no physical memory\n");
	unlock(&palloc);
	if(u == 0)
		panic("newpage");
	u->p->state = Wakeme;
	alarm(1000, wakeme, u->p);
	sched();
	goto loop;
    out:
	if(p->o){
		print("page in use %lux %lux %lux\n", p->va, p->o, origalloc.arena);
		print("%c %lux %lux, %d %d %d\n", devchar[p->o->type], p->o->va, p->o->qid, p->o->flag, p->o->nproc, p->o->npte);
		panic("shit");
	}
	p->ref = 1;
	usepage(p, 0);
	unlock(&palloc);
	if(!noclear)
		memset((void*)(p->pa|KZERO), 0, BY2PG);
	p->o = o;
	p->va = va;

	return p;
}

/*
 * Move page to head of list
 */
void
usepage(Page *p, int dolock)
{
	if(dolock)
		lock(&palloc);
	/*
	 * Unlink
	 */
	if(p->prev)
		p->prev->next = p->next;
	else
		palloc.head = p->next;
	if(p->next)
		p->next->prev = p->prev;
	else
		palloc.tail = p->prev;
	/*
	 * Link
	 */
	p->next = palloc.head;
	p->prev = 0;
	if(p->next)
		p->next->prev = p;
	else
		palloc.tail = p;
	palloc.head = p;
	if(dolock)
		unlock(&palloc);
}

Orig*
lookorig(ulong va, ulong npte, int flag, Chan *c)
{
	Orig *o;
	ulong i;

	for(o=origalloc.arena,i=0; i<conf.norig; i++,o++)
		if(o->npage && o->qid==c->qid && o->va==va){
			lock(o);
			if(o->npage && o->qid==c->qid)
			if(o->va==va && o->npte==npte && o->flag==flag)
			if(o->type==c->type && o->dev==c->dev){
				if(o->chan == 0){
					o->chan = c;
					incref(c);
				}
				o->nproc++;
				unlock(o);
				return o;
			}
			unlock(o);
		}
	return 0;
}

Orig*
neworig(ulong va, ulong npte, int flag, Chan *c)
{
	Orig *o;
	int i, freed;

	lock(&origalloc);
loop:
	if(o = origalloc.free){		/* assign = */
		origalloc.free = o->next;
		o->va = va;
		o->pte = 0;
		o->flag = flag;
		o->nproc = 1;
		o->npage = 0;
		o->chan = c;
		if(c){
			o->type = c->type;
			o->dev = c->dev;
			o->qid = c->qid;
			incref(c);
		}else{
			o->type = -1;
			o->dev = -1;
			o->qid = -1;
		}
		growpte(o, npte);
		unlock(&origalloc);
		return o;
	}
	/*
	 * This is feeble.  Orig's should perhaps be held in
	 * an LRU list.  This algorithm is too aggressive.
	 */
	freed = 0;
	for(o=origalloc.arena,i=0; i<conf.norig; i++,o++){
		if(o->nproc==0 && canlock(o)){
			if(o->nproc){
				unlock(o);
				continue;
			}
			freepage(o);
			freepte(o);
			unlock(o);
			o->next = origalloc.free;
			origalloc.free = o;
			freed++;
		}
	}
	if(freed)
		goto loop;
	print("no origs freed\n");
	unlock(&origalloc);
	if(u == 0)
		panic("neworig");
	u->p->state = Wakeme;
	alarm(1000, wakeme, u->p);
	sched();
	lock(&origalloc);
	goto loop;
}

PTE*
newmod(void)
{
	PTEA *pte;

loop:
	lock(&modalloc);
	if(pte = modalloc.free){		/* assign = */
		modalloc.free = pte->next;
		unlock(&modalloc);
		memset(pte, 0, sizeof(PTE));
		return pte;
	}
	unlock(&modalloc);
	print("no mods\n");
	if(u == 0)
		panic("newmod");
	u->p->state = Wakeme;
	alarm(1000, wakeme, u->p);
	sched();
	goto loop;
}

/*
 * Duplicate mod structure for this segment (old) in new process p.
 * old->o must be locked.
 */
void
forkmod(Seg *old, Seg *new, Proc *p)
{
	Orig *o;
	PTE *pte, *ppte, *opte, *npte;
	ulong va;

	o = old->o;
	ppte = 0;
	pte = old->mod;
	while(pte){
if(pte->page==0) panic("forkmod zero page");
if(pte->proc != u->p) panic("forkmod wrong page");
		npte = newmod();
		npte->proc = p;
		npte->page = pte->page;
		pte->page->ref++;
		o->npage++;
		/*
		 * Link into mod list for this va
		 */
		npte->nextmod = pte->nextmod;
		pte->nextmod = npte;
		/*
		 * Link into mod list for new segment
		 */
		if(ppte == 0)
			new->mod = npte;
		else
			ppte->nextva = npte;
		npte->nextva = 0;
		ppte = npte;
		pte = pte->nextva;
	}
}

void
freesegs(int save)
{
	int i, j;
	Seg *s;
	Orig *o;
	PTE *pte, *opte;
	PTEA *old;
	Page *pg;
	Chan *c;

	s = u->p->seg;
	for(i=0; i<NSEG; i++,s++){
		if(i == save)
			continue;
		o = s->o;
		if(o == 0)
			continue;
		lock(o);
		if(pte = s->mod){	/* assign = */
			while(pte){
				opte = &o->pte[(pte->page->va-o->va)>>PGSHIFT];
				while(opte->nextmod != pte){
					if(opte->page && opte->page->va != pte->page->va)
						panic("pte %lux %lux\n", opte->page->va, pte->page->va);
					opte = opte->nextmod;
					if(opte == 0)
						panic("freeseg opte==0");
				}
				opte->nextmod = pte->nextmod;
				pg = pte->page;
				if(pg->ref == 1){
					pte->page = 0;
					pg->o = 0;
				}
				pg->ref--;
				o->npage--;
				old = (PTEA*)pte;
				pte = pte->nextva;
				lock(&modalloc);
				old->next = modalloc.free;
				modalloc.free = old;
				unlock(&modalloc);
			}
		}
		o->nproc--;
		if(o->nproc == 0){
			if(c = o->chan){	/* assign = */
				o->chan = 0;
				close(c);
			}
			if(!(o->flag&OCACHED) || o->npage==0){
				freepage(o);
				freepte(o);
				unlock(o);
				lock(&origalloc);
				o->next = origalloc.free;
				origalloc.free = o;
				unlock(&origalloc);
			}else
				unlock(o);
		}else{
			/*
			 * BUG: there is a leak here. if the origin pte is being used only
			 * by the exiting process, the associated page will linger.  the fix
			 * is to remember either the length of the mod list at each va or
			 * the number of processes sharing the origin pte, and to promote one
			 * of the mods to the origin pte when no process is left using the
			 *  origin pte.
			 */
			unlock(o);
		}
	}
}

/*
 * Adjust segment to desired size.  This implementation is rudimentary.
 */
int
segaddr(Seg *s, ulong min, ulong max)
{
	Orig *o;

	if(max < min)
		return 0;
	if(min != s->minva)	/* can't grow down yet (stacks: fault.c) */
		return 0;
	max = (max+(BY2PG-1)) & ~(BY2PG-1);
	o = s->o;
	if(max == s->maxva)
		return 1;
	if(max > s->maxva){
		/*
		 * Grow
		 */
		/* BUG: check spill onto other segments */
		if(o->va+BY2PG*o->npte < max)
			growpte(o, (max-o->va)>>PGSHIFT);
		s->maxva = max;
		return 1;
	}
	/*
	 * Shrink
	 */
	print("segaddr shrink");
	for(;;);
}

/*
 * o is locked
 */
void
freepage(Orig *o)
{
	PTE *pte;
	Page *pg;
	int i;

	pte = o->pte;
	for(i=0; i<o->npte; i++,pte++)
		if(pg = pte->page){	/* assign = */
			if(pg->ref == 1){
				pte->page = 0;
				pg->o = 0;
			}
			pg->ref--;
		}
	o->npage = 0;
}

/*
 * Compacting allocator
 */

void
freepte(Orig *o)	/* o is locked */
{
	PTEA *p;
	p = (PTEA*)(o->pte - 1);
	p->o = 0;
}

void
growpte(Orig *o, ulong n)
{
	PTEA *p;
	ulong nfree;

	lock(&ptealloc);
	lock(o);
	if(o->pte){
		if(o->npte == n)
			panic("growpte pointless");
		p = (PTEA*)(o->pte - 1);
		if(o->npte > n){
			nfree = o->npte - n;
			p->n -= nfree;
			o->npte -= nfree;
			p += p->n;
			p->o = 0;
			p->n = nfree;
		}else{
			n++;
			if(p+p->n == ptealloc.free){
				compactpte(o, n - p->n);
				p = (PTEA*)(o->pte - 1);
				ptealloc.free += n - p->n;
			}else{
				compactpte(o, n);
				p = ptealloc.free;
				ptealloc.free += n;
				memcpy(p+1, o->pte, o->npte*sizeof(PTE));
				p->o = o;
				((PTEA*)(o->pte-1))->o = 0;
				o->pte = p+1;
			}
			memset(p+1+o->npte, 0, (n-(1+o->npte))*sizeof(PTE));
			p->n = n;
			o->npte = n-1;
		}
		unlock(o);
		unlock(&ptealloc);
		return;
	}
	n++;
	compactpte(o, n);
	p = ptealloc.free;
	ptealloc.free += n;
	memset(p, 0, n*sizeof(PTE));
	p->n = n;
	p->o = o;
	o->pte = p+1;
	o->npte = n-1;
	unlock(o);
	unlock(&ptealloc);
}

void
compactpte(Orig *o, ulong n)
{
	PTEA *p1, *p2;
	Orig *p2o;

	if(ptealloc.end-ptealloc.free >= n)
		return;
	p1 = ptealloc.arena;	/* dest */
	p2 = ptealloc.arena;	/* source */
	while(p2 < ptealloc.free){
		p2o = p2->o;
		if(p2o == 0){
    Free:
			p2 += p2->n;
			continue;
		}
		if(p1 != p2){
			if(p2o != o)
				lock(p2o);
			if(p2->o != p2o){	/* freepte()d very recently */
				if(p2->o)
					panic("compactpte p2->o %lux\n", p2->o);
				unlock(p2o);
				goto Free;
			}
			memcpy(p1, p2, p2->n*sizeof(PTE));
			p2o->pte = p1+1;
			if(p2o != o)
				unlock(p2o);
		}
		p2 += p1->n;
		p1 += p1->n;
	}
	ptealloc.free = p1;
	if(ptealloc.end-ptealloc.free >= n)
		return;
	unlock(o);
	unlock(&ptealloc);
	panic("compactpte %d %lux %d", n, o->va, o->npte);
}
.
## diffname port/page.c 1990/0303
## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/page.c /n/bootesdump/1990/0303/sys/src/9/mips/page.c
298a
			o->mqid = -1;
			o->mchan = 0;
.
297d
293a
			o->mchan = c->mchan;
			o->mqid = c->mqid;
.
292d
260c
			if(o->mchan==c->mchan && o->mqid==c->mqid && o->type==c->type){
.
190d
101c
	here=0;
.
88,90c
		print("%lux %lux %d\n", p->pa, p->va, p->ref);
		if(p->o){
			print("\t%d %lux %c\n", p->o->nproc, p->o->qid, devchar[p->o->type]);
			delay(100);	/* let it drain; there's a lot here */
		}
.
81,84c
	do;while(here);
	here=1;
.
79a
	static int here;
.
## diffname port/page.c 1990/0312
## diff -e /n/bootesdump/1990/0303/sys/src/9/mips/page.c /n/bootesdump/1990/0312/sys/src/9/mips/page.c
437a
o->nmod--;
.
378a
o->nmod++;
.
352a
DEBUG();
panic("mods");
.
289a
o->nmod = 0;
.
## diffname port/page.c 1990/0409
## diff -e /n/bootesdump/1990/0312/sys/src/9/mips/page.c /n/bootesdump/1990/0409/sys/src/9/mips/page.c
191a
	pprint("no physical memory\n");
.
## diffname port/page.c 1990/0617
## diff -e /n/bootesdump/1990/0409/sys/src/9/mips/page.c /n/bootesdump/1990/0617/sys/src/9/mips/page.c
209,210c
	if(!noclear){
		k = kmap(p);
		memset((void*)VA(k), 0, BY2PG);
		kunmap(k);
	}
.
163a
	KMap *k;
.
13c
	Page	*page;		/* base of Page structures, indexed by phys page number */
.
## diffname port/page.c 1990/0720
## diff -e /n/bootesdump/1990/0617/sys/src/9/mips/page.c /n/bootesdump/1990/0720/sys/src/9/mips/page.c
495a
if(max > 20*1024*1024) pprint("segaddr %lux\n", max);
.
## diffname port/page.c 1990/0728
## diff -e /n/bootesdump/1990/0720/sys/src/9/mips/page.c /n/bootesdump/1990/0728/sys/src/9/mips/page.c
604a
    Return:
.
592,594c
		goto Return;
.
566a
			print("growpte shrink");
			goto Return;
.
563,564c
		if(o->npte == n){
if(u && u->p) print("%s: ", u->p->text);
			print("growpte pointless\n");
			goto Return;
		}
.
## diffname port/page.c 1990/0801
## diff -e /n/bootesdump/1990/0728/sys/src/9/mips/page.c /n/bootesdump/1990/0801/sys/src/9/mips/page.c
533a
				unusepage(pg, 1);
.
496c
if(max > 20*1024*1024) {pprint("segaddr %lux\n", max);print("segaddr %lux\n", max);}
.
253a
/*
 * Move page to tail of list
 */
void
unusepage(Page *p, int dolock)
{
return;
	if(dolock)
		lock(&palloc);
	/*
	 * Unlink
	 */
	if(p->prev)
		p->prev->next = p->next;
	else
		palloc.head = p->next;
	if(p->next)
		p->next->prev = p->prev;
	else
		palloc.tail = p->prev;
	/*
	 * Link
	 */
	p->prev = palloc.tail;
	p->next = 0;
	if(p->prev)
		p->prev->next = p;
	else
		palloc.head = p;
	palloc.tail = p;
	if(dolock)
		unlock(&palloc);
}

.
## diffname port/page.c 1990/0802
## diff -e /n/bootesdump/1990/0801/sys/src/9/mips/page.c /n/bootesdump/1990/0802/sys/src/9/mips/page.c
687c
	if(u && u->p)
		print("%s: %s: ", u->p->text, u->p->pgrp->user);
	print("compactpte fails addr %lux\n", o->va+n*BY2PG);
	return 0;
.
684c
		return 1;
.
655c
		return 1;
.
648c
int
.
645a
	return;

    Trouble:
	unlock(&ptealloc);
	if(u && u->p)
		error(0, Enovmem);
	panic("growpte fails %d %lux %d\n", n, o->va, o->npte);
.
644d
635c
	if(!compactpte(o, n))
		goto Trouble;
.
620c
				if(!compactpte(o, n))
					goto Trouble;
.
616c
				if(!compactpte(o, n - p->n))
					goto Trouble;
.
596d
543a
		unlock(o);
		poperror();
.
541a
		lock(o);
		if(waserror()){
			unlock(o);
			nexterror();
		}
.
530d
342a
		if(u && u->p)
			poperror();
		unlock(o);
.
341a
		lock(o);
		if(u && u->p && waserror()){
			unlock(o);
			unlock(&origalloc);
			nexterror();
		}
.
260d
6a
#include	"errno.h"
.
## diffname port/page.c 1990/0814
## diff -e /n/bootesdump/1990/0802/sys/src/9/mips/page.c /n/bootesdump/1990/0814/sys/src/9/mips/page.c
665a
	unlock(o);
.
661a
	unlock(o);
.
647a
		memset(p+1+o->npte, 0, (n-(1+o->npte))*sizeof(PTE));
		p->n = n;
		o->npte = n-1;
.
628,646c
			if(!compactpte(o, n))
				goto Trouble;
			p = ptealloc.free;
			ptealloc.free += n;
			memcpy(p+1, o->pte, o->npte*sizeof(PTE));
			p->o = o;
			((PTEA*)(o->pte-1))->o = 0;
			o->pte = p+1;
.
618,626c
		n++;
		if(p+p->n == ptealloc.free){
			if(!compactpte(o, n - p->n))
				goto Trouble;
			p = (PTEA*)(o->pte - 1);
			ptealloc.free += n - p->n;
.
616d
612,614c
		if(o->npte >= n)
.
610a
	lock(o);
.
603a
/*
 * o is locked.  this will always do a grow; if n<=o->npte someone
 * else got here first and we can just return.
 */
.
557,558d
550,554d
351d
344d
342d
## diffname port/page.c 1990/1013
## diff -e /n/bootesdump/1990/0814/sys/src/9/mips/page.c /n/bootesdump/1990/1013/sys/src/9/mips/page.c
426c
		npte = newmod(o);
.
400c
panic("mods %lux %d %d", o->va, o->npte, o->nmod);
.
385c
newmod(Orig *o)
.
## diffname port/page.c 1990/1018
## diff -e /n/bootesdump/1990/1013/sys/src/9/mips/page.c /n/bootesdump/1990/1018/sys/src/9/mips/page.c
465a
		s->o = 0;	/* seg() won't match it (e.g. in procread()) */
.
## diffname port/page.c 1990/1101
## diff -e /n/bootesdump/1990/1018/sys/src/9/mips/page.c /n/bootesdump/1990/1101/sys/src/9/mips/page.c
374a
	if(freebroken())
		goto lockloop;
	print("no origs freed\n");
.
373d
318a
lockloop:
.
197a
	print("no physical memory\n");
	pprint("no physical memory\n");
.
195a
	if(freebroken())
		goto loop;
.
193,194d
## diffname port/page.c 1990/1115
## diff -e /n/bootesdump/1990/1101/sys/src/9/mips/page.c /n/bootesdump/1990/1115/sys/src/9/mips/page.c
562c
	pexit("Suicide", 0);
.
## diffname port/page.c 1990/11211
## diff -e /n/bootesdump/1990/1115/sys/src/9/mips/page.c /n/bootesdump/1990/11211/sys/src/9/mips/page.c
656c
		error(Enovmem);
.
493d
432d
404,405d
341,342c
			o->qid = (Qid){~0, ~0};
			o->mqid = (Qid){~0, ~0};
.
332d
301c
			if(o->mchan==c->mchan && o->type==c->type && eqqid(o->mqid, c->mqid)){
.
299c
			if(o->npage && eqqid(o->qid, c->qid))
.
297c
		if(o->npage && o->qid.path==c->qid.path && o->va==va){
.
## diffname port/page.c 1990/1126
## diff -e /n/bootesdump/1990/11211/sys/src/9/mips/page.c /n/bootesdump/1990/1126/sys/src/9/mips/page.c
339c
			o->type = ~0;
.
## diffname port/page.c 1990/1211
## diff -e /n/bootesdump/1990/1211/sys/src/9/mips/page.c /n/bootesdump/1990/1211/sys/src/9/port/page.c
154c
		if(ppn < conf.npage0)
			p->pa = conf.base0+(ppn<<PGSHIFT);
		else
			p->pa = conf.base1+((ppn-conf.npage0)<<PGSHIFT);
.
72a
	if(palloc.addr >= conf.maxialloc)
		panic("keep bill joy away");
.
## diffname port/page.c 1990/1212
## diff -e /n/bootesdump/1990/1211/sys/src/9/port/page.c /n/bootesdump/1990/1212/sys/src/9/port/page.c
579c
				unusepage(pg, dolock);
.
569c
freepage(Orig *o, int dolock)
.
509c
				freepage(o, 1);
.
370c
			freepage(o, 1);
.
188c
				freepage(o1, 0);
.
58c
	if(palloc.active && n!=0)
.
## diffname port/page.c 1990/1214
## diff -e /n/bootesdump/1990/1212/sys/src/9/port/page.c /n/bootesdump/1990/1214/sys/src/9/port/page.c
344c
			o->type = 0xFFFF;
.
## diffname port/page.c 1990/1226
## diff -e /n/bootesdump/1990/1214/sys/src/9/port/page.c /n/bootesdump/1990/1226/sys/src/9/port/page.c
701c
	print("compactpte fails addr %lux %lux %d\n", o->va+n*BY2PG, o->va, n);
.
## diffname port/page.c 1991/0110
## diff -e /n/bootesdump/1990/1226/sys/src/9/port/page.c /n/bootesdump/1991/0110/sys/src/9/port/page.c
211c
		print("page in use %lux %lux %lux %lux\n", p, p->va, p->o, origalloc.arena);
.
88c
	nf = nb = 0;
.
## diffname port/page.c 1991/0115
## diff -e /n/bootesdump/1991/0110/sys/src/9/port/page.c /n/bootesdump/1991/0115/sys/src/9/port/page.c
466a
	/*
	 * flushvirt() is a no-op on machines without virtual write-back caches.
	 * On such machines it is necessary to make sure the caches are flushed
	 * before the pages are remapped.
	 */
	flushvirt();
.
## diffname port/page.c 1991/0318
## diff -e /n/bootesdump/1991/0115/sys/src/9/port/page.c /n/bootesdump/1991/0318/sys/src/9/port/page.c
692c
			memmove(p1, p2, p2->n*sizeof(PTE));
.
633c
			memmove(p+1, o->pte, o->npte*sizeof(PTE));
.
## diffname port/page.c 1991/0425
## diff -e /n/bootesdump/1991/0318/sys/src/9/port/page.c /n/bootesdump/1991/0425/sys/src/9/port/page.c
49a
extern long end;

.
## diffname port/page.c 1991/0606
## diff -e /n/bootesdump/1991/0425/sys/src/9/port/page.c /n/bootesdump/1991/0606/sys/src/9/port/page.c
709a
	return 0;
}

long
ibrk(ulong addr, int seg)
{
	Seg *s;

	s = &u->p->seg[seg];
	if(seg == LSEG && s->o == 0)
		mklockseg(s);

	/* Allows us to determine the base of the segment */
	if(addr == 0)
		return s->minva;

	if(addr < s->endseg){
		pprint("addr below segment\n");
		pexit("Suicide", 0);
		error(Esegaddr);
	}

	if(addr > PGROUND(s->endseg))
		if(segaddr(s, s->minva, addr) == 0){
			pprint("bad segaddr in brk\n");
			pexit("Suicide", 0);
			error(Esegaddr);
		}

	s->endseg = addr;
.
552c
	max = PGROUND(max);
.
71,74c
	if(align)
		palloc.addr = PGROUND(palloc.addr);

.
64,67c
	if(align)
		palloc.addr = PGROUND(palloc.addr);

.
## diffname port/page.c 1991/0607
## diff -e /n/bootesdump/1991/0606/sys/src/9/port/page.c /n/bootesdump/1991/0607/sys/src/9/port/page.c
590a
	}
.
585c
				(*o->freepg)(pg, dolock);
.
582c
	for(i=0; i<o->npte; i++,pte++) {
.
431,432d
336a
		o->freepg = unusepage;
.
## diffname port/page.c 1991/0705
## diff -e /n/bootesdump/1991/0607/sys/src/9/port/page.c /n/bootesdump/1991/0705/sys/src/9/port/page.c
730,738c
	lock(&ptealloclk);
	p->next = ptealloclk.free;
	ptealloclk.free = p;
	unlock(&ptealloclk);
.
720,727c
	switch(s->type&SG_TYPE) {
	case SG_PHYSICAL:
		for(pg = p->pages; pg < ptop; pg++)
			if(*pg)
				(*s->pgfree)(*pg);
		break;
	default:
		for(pg = p->pages; pg < ptop; pg++)
			if(*pg)
				putpage(*pg);
.
716,718c
	ptop = &p->pages[PTEPERTAB];
.
714c
	Page **pg, **ptop;
.
711,712c
void
freepte(Segment *s, Pte *p)
.
700,708c

	new = ptealloclk.free;
	ptealloclk.free = new->next;
	unlock(&ptealloclk);
	memset(new->pages, 0, sizeof(new->pages));
	return new;
.
672,698c
	lock(&ptealloclk);
	while(ptealloclk.free == 0) {
		unlock(&ptealloclk);

		k = kmap(newpage(1, 0, 0));
		new = (Pte*)VA(k);
		n = (BY2PG/sizeof(Pte))-1;
		for(i = 0; i < n; i++)
			new[i].next = &new[i+1];

		lock(&ptealloclk);
		ptealloclk.pages++;
		new[i].next = ptealloclk.free;
		ptealloclk.free = new;
.
669,670c
	Pte *new;
	int i, n;
	KMap *k;
.
666,667c
Pte*
ptealloc(void)
.
658,663c
	return new;		
.
638,656d
616,636c
	end = &old->pages[PTEPERTAB];
	for(src = old->pages, dst = new->pages; src < end; src++, dst++)
		if(*src) {
			if(onswap(*src))
				dupswap(*src);
			else {
				lockpage(*src);
				(*src)->ref++;
				unlockpage(*src);
			}
			*dst = *src;
.
606,614c
	new = ptealloc();
.
601,604c
	Page **src, **dst, **end;
	Pte *new;
.
594,599c
Pte*
ptecpy(Pte *old)
.
591c
	unlock(&palloc.hashlock);
	return 0;
.
588c

			lock(&palloc);
			if(++f->ref == 1) {
				if(f->prev) 
					f->prev->next = f->next;
				else
					palloc.head = f->next;

				if(f->next)
					f->next->prev = f->prev;
				else
					palloc.tail = f->prev;
				palloc.freecount--;
			}
			unlock(&palloc);

			unlockpage(f);
			return f;	
.
580,586c
	lock(&palloc.hashlock);
	for(f = palloc.hash[PGHFUN(i, daddr)]; f; f = f->hash) {
		if(f->image == i && f->daddr == daddr) {
			unlock(&palloc.hashlock);

			lockpage(f);
			if(f->image != i || f->daddr != daddr) {
				unlockpage(f);
				return 0;
.
576,578c
	Page *f;
.
570,574c
Page *
lookpage(Image *i, ulong daddr)
.
545,567c
	incref(i);
	lock(&palloc.hashlock);
	p->image = i;
	l = &pghash(p);
	p->hash = *l;
	*l = p;
	unlock(&palloc.hashlock);
.
543c
	Page **l;
.
537,541c
void
cachepage(Page *p, Image *i)
.
507,533c
		unlock(&palloc.hashlock);
		putimage(p->image);
		p->image = 0;
.
505a
			l = &f->hash;
.
466,504c
	if(p->image) {
		lock(&palloc.hashlock);
		l = &pghash(p);
		for(f = *l; f; f = f->hash) {
			if(f == p) {
				*l = p->hash;
				break;
.
458,464c
	Page **l, *f;
.
456c
uncachepage(Page *p)				/* Alway called with a locked page */
.
428,452c
	ks = kmap(f);
	kd = kmap(t);
	memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
	kunmap(ks);
	kunmap(kd);
.
424,426c
	KMap *ks, *kd;
.
422c
copypage(Page *f, Page *t)
.
417,420d
407,414c
	
	uncachepage(np);
	np->va = p->va;
	np->daddr = p->daddr;
	copypage(p, np);
	cachepage(np, p->image);
	unlockpage(np);
	uncachepage(p);
.
399,405c
	lockpage(np);				/* Cache the new version */
	if(np->ref != 0) {			/* Stolen by new page */
		uncachepage(p);
		unlockpage(np);
		return;
.
394,397c
	unlock(&palloc);
.
379,392c
	else {
		palloc.head = palloc.tail = np;
		np->prev = np->next = 0;
	}
.
360,377c

	np = palloc.head;			/* Allocate a new page from freelist */
	if(palloc.head = np->next)		/* = Assign */
		palloc.head->prev = 0;
	else
		palloc.tail = 0;

	if(palloc.tail) {			/* Link back onto tail to give us lru */
		np->prev = palloc.tail;
		palloc.tail->next = np;
		np->next = 0;
		palloc.tail = np;
.
326,358c
	lock(&palloc);

	if(palloc.freecount < HIGHWATER || /* No freelist cache when memory is very low */
	   p->image == &swapimage) {	   /* No dup for swap pages */
		unlock(&palloc);
		uncachepage(p);	
		return;
.
323,324c
	Page *np;
.
320,321c
void
duppage(Page *p)				/* Always call with p locked */
.
317c
		else {
			if(palloc.head) {
				p->next = palloc.head;
				palloc.head->prev = p;
				p->prev = 0;
				palloc.head = p;
			}
			else {
				palloc.head = palloc.tail = p;
				p->prev = p->next = 0;
			}
		}

		palloc.freecount++;		/* Release people waiting for memory */
		unlock(&palloc);
	}
	unlockpage(p);

	if(palloc.wanted)
		wakeup(&palloc.r);
.
315c
			else {
				palloc.head = palloc.tail = p;
				p->prev = p->next = 0;
			}
.
301,313c
	lockpage(p);
	if(--p->ref == 0) {
		lock(&palloc);
		if(p->image) {
			if(palloc.tail) {
				p->prev = palloc.tail;
				palloc.tail->next = p;
				p->next = 0;
				palloc.tail = p;
.
295,299c
	if(onswap(p)) {
		putswap(p);
		return;
	}
.
268,293c
	int count;
.
266c
putpage(Page *p)
.
262,264d
235,259c
	return palloc.freecount >= HIGHWATER;
.
229,233c
int
ispages(void *p)
.
223,224d
203,218c

	uncachepage(p);
	p->ref++;
	p->va = va;
	p->modref = 0;
	for(i = 0; i < MAXMACH; i++)
		p->cachectl[i] = PG_NOFLUSH;
	unlockpage(p);

	if(clear){
.
199,201c

	lockpage(p);

	if(p->ref != 0)
.
197a

	p = palloc.head;
	if(palloc.head = p->next)		/* = Assign */
		palloc.head->prev = 0;
	else
		palloc.tail = 0;

	palloc.freecount--;
.
196c
		qlock(&palloc.pwait);			/* Hold memory requesters here */

		kickpager();
		tsleep(&palloc.r, ispages, 0, 1000);

		qunlock(&palloc.pwait);
		lock(&palloc);
		palloc.wanted--;
.
176,194c

	/* The kp test is a poor guard against the pager deadlocking */
	while((palloc.freecount < HIGHWATER && u->p->kp == 0) || palloc.freecount == 0) {
		palloc.wanted++;
		unlock(&palloc);			
		if(s && *s) {
			qunlock(&((*s)->lk));
			*s = 0;
.
174c

.
170a
	int i;
.
169d
166c
newpage(int clear, Segment **s, ulong va)
.
159a
		palloc.freecount++;
.
152c

	pmem = ((conf.npage-ppn)*BY2PG)/1024;
	vmem = pmem + ((conf.nswap)*BY2PG)/1024;
	palloc.user = conf.npage-ppn;
	print("%lud free pages, %dK bytes, swap %dK bytes\n", palloc.user, pmem, vmem);

.
140,141c
	pa = (conf.npage<<PGSHIFT) - nb; /* physical addr of first free page */
	ppn = pa >> PGSHIFT;		 /* physical page number of first free page */
.
117,134d
114,115d
112c
	ulong i, vmem, pmem;
.
79,108d
74a

.
50c
void
unlockpage(Page *p)
{
	p->lock = 0;
}
.
45,48c
	for(;;) {
		if(p->lock == 0) {
			s = splhi();
			lock(&pglock);
			if(p->lock == 0) {
				p->lock = 1;
				unlock(&pglock);
				splx(s);
				return;
			}
			unlock(&pglock);
			splx(s);
		}
		sched();
	}
}
.
37,43c
/* Multiplex a hardware lock for per page manipulations */
void
lockpage(Page *p)
{	
	int s;
.
27,35c
extern long end;
static Lock pglock;
.
23,25c
	Pte	*free;
	int	pages;
}ptealloclk;
.
20c
struct Palloc palloc;

struct Ptealloc
.
9,18c
#define PGHFUN(x, y)	(((ulong)x^(ulong)y)%PGHSIZE)
#define	pghash(s)	palloc.hash[PGHFUN(s->image, p->daddr)]
.
## diffname port/page.c 1991/0718
## diff -e /n/bootesdump/1991/0705/sys/src/9/port/page.c /n/bootesdump/1991/0718/sys/src/9/port/page.c
299c
uncachepage(Page *p)				/* Always called with a locked page */
.
## diffname port/page.c 1991/0801
## diff -e /n/bootesdump/1991/0718/sys/src/9/port/page.c /n/bootesdump/1991/0801/sys/src/9/port/page.c
67a
	if(palloc.addr+n > conf.base0 + conf.npage0*BY2PG)
		palloc.addr = conf.base1;

.
## diffname port/page.c 1991/0802
## diff -e /n/bootesdump/1991/0801/sys/src/9/port/page.c /n/bootesdump/1991/0802/sys/src/9/port/page.c
123a

	palloc.user = palloc.freecount = p - palloc.head;
	pmem = palloc.user*BY2PG/1024;
	vmem = pmem + ((conf.nswap)*BY2PG)/1024;
	print("%lud free pages, %dK bytes, swap %dK bytes\n", palloc.user, pmem, vmem);
.
121a
	addr = palloc.addr1 = PGROUND(palloc.addr1);
	lim = conf.base1 + (conf.npage1<<PGSHIFT);
	for(; addr < lim; addr += BY2PG){
		p->next = p+1;
		p->prev = p-1;
		p->pa = addr;
		p++;
	}
	palloc.tail = p - 1;
.
116,120c
		p->pa = addr;
		p++;
.
104,113c
	/*
 	 *  for each page in each bank, point a page structure to
	 *  the page and chain it into the free list
	 */
	p = palloc.head;
	addr = palloc.addr0 = PGROUND(palloc.addr0);
	lim = conf.base0 + (conf.npage0<<PGSHIFT);
	for(; addr < lim; addr += BY2PG){
.
101,102c
	palloc.head = ialloc(np*sizeof(Page), 0);
	palloc.active = 1;
.
99c
	 *  allocate Page structs (no more ialloc's allowed after this).
	 *  np is useless after this ialloc since we've just eaten up
	 *  some pages for the Page structures.
.
92,97d
90c
	/*
	 *  calculate an upper bound to the number of pages structures
	 *  we'll need (np).
	 */
	np = (conf.npage0<<PGSHIFT) - (palloc.addr0 - conf.base0);
	np += (conf.npage1<<PGSHIFT) - (palloc.addr1 - conf.base1);
	np = np>>PGSHIFT;
.
86c
	ulong np, addr, lim;
.
79a
	/*
	 *  zero it
	 */
	memset((void*)(p|KZERO), 0, n);

	/*
	 *  don't put anything else into a page aligned ialloc
	 */
	*ap = align ? PGROUND(p+n) : (p+n);

.
77,78c
	if(p >= conf.maxialloc)
		panic("keep bill joy away 2");
.
71,75c
	/*
	 *  try first bank
	 */
	p = align ? PGROUND(palloc.addr0) : palloc.addr0;
	if(p+n > conf.base0 + (conf.npage0<<PGSHIFT)){
		/*
		 *  no room in first bank, try second bank
		 */
		if(conf.npage1 <= 0)
			panic("keep bill joy away 1");
		p = align ? PGROUND(palloc.addr1) : palloc.addr1;
		ap = &palloc.addr1;
	} else
		ap = &palloc.addr0;
.
68,69c
	if(palloc.addr0 == 0){
		palloc.addr0 = ((ulong)&end)&~KZERO;
		palloc.addr1 = conf.base1;
	}
.
63,66d
59a
	ulong *ap;
.
54c
 *  Called to allocate permanent data structures, before calling pageinit().
 *  We assume all of text+data+bss is in the first memory bank.
.
## diffname port/page.c 1991/0806
## diff -e /n/bootesdump/1991/0802/sys/src/9/port/page.c /n/bootesdump/1991/0806/sys/src/9/port/page.c
179a

		poperror();
.
177a
		if(waserror()) {
			qunlock(&palloc.pwait);
			lock(&palloc);
			palloc.wanted--;
			unlock(&palloc);
			nexterror();
		}

.
171c
		unlock(&palloc);
.
## diffname port/page.c 1991/0807
## diff -e /n/bootesdump/1991/0806/sys/src/9/port/page.c /n/bootesdump/1991/0807/sys/src/9/port/page.c
67c
		/* addr0 and addr1 are physical addresses */
		palloc.addr0 = (((ulong)&end)&~KZERO) + conf.base0;
.
## diffname port/page.c 1991/0906
## diff -e /n/bootesdump/1991/0807/sys/src/9/port/page.c /n/bootesdump/1991/0906/sys/src/9/port/page.c
179,185c
		while(waserror())			/* Ignore interrupts */
			;
.
## diffname port/page.c 1991/1003
## diff -e /n/bootesdump/1991/0906/sys/src/9/port/page.c /n/bootesdump/1991/1003/sys/src/9/port/page.c
276a
simpleputpage(Page *pg)			/* Always call with palloc locked */
{
	pg->ref = 0;
	palloc.freecount++;
	if(palloc.head) {
		pg->next = palloc.head;
		palloc.head->prev = pg;
		pg->prev = 0;
		palloc.head = pg;
	}
	else {
		palloc.head = palloc.tail = pg;
		pg->prev = pg->next = 0;
	}
}

void
.
## diffname port/page.c 1991/1115
## diff -e /n/bootesdump/1991/1003/sys/src/9/port/page.c /n/bootesdump/1991/1115/sys/src/9/port/page.c
225a
	USED(p);
.
## diffname port/page.c 1991/1122
## diff -e /n/bootesdump/1991/1115/sys/src/9/port/page.c /n/bootesdump/1991/1122/sys/src/9/port/page.c
497c
		for(pg = p->first; pg <= p->last; pg++)
.
491a
		ptop = &p->pages[PTEPERTAB];
.
488,489d
479a
	new->first = &new->pages[PTEPERTAB];
	new->last = new->pages;
.
464c
		k = kmap(newpage(0, 0, 0));
.
446a
			new->last = dst;
.
436,438c
	dst = &new->pages[old->first-old->pages];
	new->first = dst;
	for(src = old->first; src <= old->last; src++, dst++)
.
## diffname port/page.c 1992/0111
## diff -e /n/bootesdump/1991/1122/sys/src/9/port/page.c /n/bootesdump/1992/0111/sys/src/9/port/page.c
7c
#include	"../port/error.h"
.
## diffname port/page.c 1992/0120
## diff -e /n/bootesdump/1992/0111/sys/src/9/port/page.c /n/bootesdump/1992/0120/sys/src/9/port/page.c
6d
## diffname port/page.c 1992/0131
## diff -e /n/bootesdump/1992/0120/sys/src/9/port/page.c /n/bootesdump/1992/0131/sys/src/9/port/page.c
500a
				*pg = 0;
			}
.
499c
			if(*pg) {
.
495a
				*pg = 0;
			}
.
494c
			if(*pg) {
.
481a

.
479d
464c
		k = kmap(newpage(1, 0, 0));
.
## diffname port/page.c 1992/0204
## diff -e /n/bootesdump/1992/0131/sys/src/9/port/page.c /n/bootesdump/1992/0204/sys/src/9/port/page.c
264a
			p->prev = 0;
.
263c
				p->next = 0;
.
258d
252a
			p->next = 0;
.
251c
				p->prev = 0;
.
246d
## diffname port/page.c 1992/0303
## diff -e /n/bootesdump/1992/0204/sys/src/9/port/page.c /n/bootesdump/1992/0303/sys/src/9/port/page.c
300,301c
	/* No freelist cache when memory is very low, No dup for swap pages */
	if(palloc.freecount < swapalloc.highwater || 
	   p->image == &swapimage) {
.
271,272c
	if(wake && palloc.wanted)
.
266a
		wake = 1;
.
263a
			palloc.head = p;
.
261c
				palloc.tail = p;
.
258d
251a
			palloc.tail = p;
.
249c
				palloc.head = p;
.
246d
242c
		if(p->image && p->image != &swapimage) {
.
238a
	wake = 0;
.
232c
	int wake;
.
226c
	return palloc.freecount >= swapalloc.highwater;
.
169c
	while((palloc.freecount < swapalloc.highwater && u->p->kp == 0)||palloc.freecount == 0) {
.
153c

	/* Pageing numbers */
	swapalloc.highwater = (palloc.freecount*5)/100;
	swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);
	hw = (swapalloc.highwater*BY2PG)/1024;
	hr = (swapalloc.headroom*BY2PG)/1024;
	
	print("%lud free pages, %dK bytes, swap %dK bytes, highwater %dK, headroom %dK\n", 
				palloc.user, pmem, vmem, hw, hr);
.
106c
	ulong i, vmem, pmem, hw, hr;
.
## diffname port/page.c 1992/0304
## diff -e /n/bootesdump/1992/0303/sys/src/9/port/page.c /n/bootesdump/1992/0304/sys/src/9/port/page.c
281,282d
276d
247d
240,241d
## diffname port/page.c 1992/0313
## diff -e /n/bootesdump/1992/0304/sys/src/9/port/page.c /n/bootesdump/1992/0313/sys/src/9/port/page.c
99a
}

/*
 *  allocate with possible page alignment
 */
void*
ialloc(ulong n, int align)
{
	return iallocspan(n, align ? BY2PG : 0, 0);
.
97c
	memset((void*)(p|KZERO), 0, n);
.
95c
	 *  zero it
.
92c
	if(palloc.addr0 < r->start && r->start <= conf.base0+(conf.npage0<<PGSHIFT))
		palloc.addr0 = r->start;
	else if(palloc.addr1 < r->start && r->start <= conf.base1+(conf.npage1<<PGSHIFT))
		palloc.addr1 = r->start;
.
90c
	 *  remember high water marks
.
88a
		/* check for crossing a crevasse */
		if(crevasse){
			ledge = p / crevasse;
			if(ledge != ((p+n-1) / crevasse))
				p = ((p+n-1) / crevasse) * crevasse;
		}

		/* see if it fits */
		if(p + n > r->end)
			continue;

		/* split the region */
		if(p != r->start)
			addsplit(r, r->start, p);
		r->start = p + n;
		break;
	}
	if(r == &region[Nregion])
		panic("out of memory");

.
86,87c
	p = 0;
	for(r = region; r < &region[Nregion]; r++){
		/* allign region */
		p = r->start;
		if(align){
			m = p % align;
			if(m)
				p += align - m;
		}
.
74,84c
	if(align){
		m = n % align;
		if(m)
			n += align - m;
	}
.
72c
	 *  alignment also applies to length
.
66,68c
		region[Nregion-2].start = (((ulong)&end)&~KZERO) + conf.base0;
		region[Nregion-2].end = conf.base0 + (conf.npage0<<PGSHIFT);
		region[Nregion-1].start = conf.base1;
		region[Nregion-1].end = conf.base1 + (conf.npage1<<PGSHIFT);

		palloc.addr0 = region[Nregion-2].start;
		palloc.addr1 = region[Nregion-1].start;
.
60c
	Region *r;
	int m;
	int ledge;
.
57c
iallocspan(ulong n, int align, ulong crevasse)
.
55a
void
addsplit(Region *r, ulong start, ulong end)
{
	Region *rr;
	int len = end - start;

	/* first look for an unused one */
	for(rr = region; rr < &region[Nregion]; rr++){
		if(rr == r)
			continue;
		if(rr->end - rr->start == 0){
			rr->start = start;
			rr->end = end;
			return;
		}
	}

	/* then look for a smaller one */
	for(rr = region; rr < &region[Nregion]; rr++){
		if(rr == r)
			continue;
		if(rr->end - rr->start < len){
			rr->start = start;
			rr->end = end;
			return;
		}
	}
}
.
54a
 *
 *  alignment is in number of bytes
 *
 *  WARNING: You can't cross a crevasse!
.
51a
typedef struct Region	Region;
struct Region
{
	ulong	start;
	ulong	end;
};

enum
{
	Nregion=	10,
};
Region region[Nregion];


.
## diffname port/page.c 1992/0315
## diff -e /n/bootesdump/1992/0313/sys/src/9/port/page.c /n/bootesdump/1992/0315/sys/src/9/port/page.c
134c
		/* align region */
.
101a

/*
 *  Called to allocate permanent data structures, before calling pageinit().
 *  We assume all of text+data+bss is in the first memory bank.
 *
 *  alignment is in number of bytes.  It pretains both to the start and
 *  end of the allocated memory.
 *
 *  If crevasse is specified, no allocation can span an address that is
 *  a multiple of crevasse.
 */
.
66,73d
20c
extern	long end;
ulong	hiaddr;
.
## diffname port/page.c 1992/0317
## diff -e /n/bootesdump/1992/0315/sys/src/9/port/page.c /n/bootesdump/1992/0317/sys/src/9/port/page.c
197a
print("addr0 %lux addr1 %lux\n", palloc.addr0, palloc.addr1);
.
100c
 *  alignment is in number of bytes.  It pertains both to the start and
.
## diffname port/page.c 1992/0318
## diff -e /n/bootesdump/1992/0317/sys/src/9/port/page.c /n/bootesdump/1992/0318/sys/src/9/port/page.c
198d
## diffname port/page.c 1992/0319
## diff -e /n/bootesdump/1992/0318/sys/src/9/port/page.c /n/bootesdump/1992/0319/sys/src/9/port/page.c
118c
		region[Nregion-2].start = (((ulong)end)&~KZERO) + conf.base0;
.
20d
## diffname port/page.c 1992/0321
## diff -e /n/bootesdump/1992/0319/sys/src/9/port/page.c /n/bootesdump/1992/0321/sys/src/9/port/page.c
2c
#include	"../port/lib.h"
.
## diffname port/page.c 1992/0618
## diff -e /n/bootesdump/1992/0321/sys/src/9/port/page.c /n/bootesdump/1992/0618/sys/src/9/port/page.c
177d
117,120c
		r = &region[Nregion-2];
		r->start = (((ulong)end)&~KZERO) + conf.base0;
		r->end = conf.base0 + (conf.npage0<<PGSHIFT);
		r++;
		r->start = conf.base1;
		r->end = conf.base1 + (conf.npage1<<PGSHIFT);
.
110d
107a
	int m;
.
84c
	for(rr = region; rr < eregion; rr++){
.
73c
	for(rr = region; rr < eregion; rr++){
.
71a
	len = end - start;
	eregion = &region[Nregion];

.
69,70c
	int len;
	Region *rr, *eregion;
.
## diffname port/page.c 1992/0619
## diff -e /n/bootesdump/1992/0618/sys/src/9/port/page.c /n/bootesdump/1992/0619/sys/src/9/port/page.c
606a
}

/* Multiplex a hardware lock for per page manipulations */
void
lockpage(Page *p)
{	
	int s;

	for(;;) {
		if(p->lock == 0) {
			s = splhi();
			lock(&pglock);
			if(p->lock == 0) {
				p->lock = 1;
				unlock(&pglock);
				splx(s);
				return;
			}
			unlock(&pglock);
			splx(s);
		}
		sched();
	}
}

void
unlockpage(Page *p)
{
	p->lock = 0;
.
269c
	while((palloc.freecount < swapalloc.highwater && u->p->kp == 0) ||
	       palloc.freecount == 0) {
.
263,265d
252,253c
	print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n", 
	palloc.user, pmem, vmem, hw/1024, hr/1024);
.
249,250c

	hw = swapalloc.highwater*BY2PG;
	hr = swapalloc.headroom*BY2PG;
.
244c
	vmem = pmem + (conf.nswap*BY2PG)/1024;
.
242c
	palloc.user = p - palloc.head;
	palloc.freecount = palloc.user;
.
235c
		p->next = p+1;
		p->pa = palloc.p1;
		palloc.p1 += BY2PG;
		palloc.np1--;
.
230,233c
	while(palloc.np1 > 0) {
.
227c
		p->next = p+1;
		p->pa = palloc.p0;
		palloc.p0 += BY2PG;
		palloc.np0--;
.
222,225c
	while(palloc.np0 > 0) {
.
209,220d
201,207c
	np = palloc.np0+palloc.np1;
	palloc.head = xalloc(np*sizeof(Page));
	if(palloc.head == 0)
		panic("pageinit");
.
199a
	ulong np, hw, hr, vmem, pmem;
.
197,198d
25,194d
23d
20,21c
static	Lock pglock;
struct	Palloc palloc;
.
11,12d
## diffname port/page.c 1992/0620
## diff -e /n/bootesdump/1992/0619/sys/src/9/port/page.c /n/bootesdump/1992/0620/sys/src/9/port/page.c
413,417c
	free(p);
.
388d
367,385c
	new = smalloc(sizeof(Pte));
.
364,365d
11,17d
## diffname port/page.c 1992/0621
## diff -e /n/bootesdump/1992/0620/sys/src/9/port/page.c /n/bootesdump/1992/0621/sys/src/9/port/page.c
24c
print("page: %lux %d %lux %d\n", palloc.p0, palloc.np0, palloc.p1, palloc.np1);
.
## diffname port/page.c 1992/0622
## diff -e /n/bootesdump/1992/0621/sys/src/9/port/page.c /n/bootesdump/1992/0622/sys/src/9/port/page.c
24c

.
## diffname port/page.c 1992/0625
## diff -e /n/bootesdump/1992/0622/sys/src/9/port/page.c /n/bootesdump/1992/0625/sys/src/9/port/page.c
386,414d
344c
				unlock(*src);
.
342c
				lock(*src);
.
332a
	Page **src, **dst, **end;
.
331d
320c
			unlock(f);
.
301c
				unlock(f);
.
299c
			lock(f);
.
272a
	unlock(&palloc.hashlock);
	putimage(p->image);
	p->image = 0;
.
269,271c
		l = &f->hash;
.
259,267c
	if(p->image == 0)
		return;

	lock(&palloc.hashlock);
	l = &pghash(p);
	for(f = *l; f; f = f->hash) {
		if(f == p) {
			*l = p->hash;
			break;
.
238c
	unlock(np);
.
229c
		unlock(np);
.
226c
	lock(np);				/* Cache the new version */
.
189a
	pg->next = palloc.head;
	palloc.head->prev = pg;
	pg->prev = 0;
	palloc.head = pg;
.
188a
		return;
.
180,186c
	if(palloc.head == 0) {
.
172c
	unlock(p);
.
141c
	lock(p);
.
115c
	unlock(p);
.
104c
	lock(p);
.
## diffname port/page.c 1992/0628
## diff -e /n/bootesdump/1992/0625/sys/src/9/port/page.c /n/bootesdump/1992/0628/sys/src/9/port/page.c
199,200c
	if(palloc.freecount < swapalloc.highwater) {
.
195a
	if(p->image == &swapimage)
		return;

.
## diffname port/page.c 1992/0629
## diff -e /n/bootesdump/1992/0628/sys/src/9/port/page.c /n/bootesdump/1992/0629/sys/src/9/port/page.c
287a
	unlock(&palloc.hashlock);
}

void
cachedel(Image *i, ulong daddr)
{
	Page *f, **l;

	lock(&palloc.hashlock);
	l = &palloc.hash[PGHFUN(i, daddr)];
	for(f = *l; f; f = f->hash) {
		if(f->image == i && f->daddr == daddr) {
			*l = f->hash;
			break;
		}
		l = &f->hash;
	}
.
200,201c
	/* No freelist cache when memory is very low */
.
197a
	}
.
196c
	/* No dup for swap pages */
	if(p->image == &swapimage) {
		uncachepage(p);	
.
## diffname port/page.c 1992/0711
## diff -e /n/bootesdump/1992/0629/sys/src/9/port/page.c /n/bootesdump/1992/0711/sys/src/9/port/page.c
353c
	Page **src, **dst;
.
## diffname port/page.c 1992/0805
## diff -e /n/bootesdump/1992/0711/sys/src/9/port/page.c /n/bootesdump/1992/0805/sys/src/9/port/page.c
90a

		/*
		 * If called from fault and we lost the segment from underneath
		 * don't waste time allocating and freeing a page. Fault will call
		 * newpage again when it has reaquired the segment locks
		 */
		if(dontalloc)
			return 0;

.
78a
			dontalloc = 1;
.
75a
		dontalloc = 0;
.
71,73c
	hw = swapalloc.highwater;
	while((palloc.freecount < hw && u->p->kp == 0) || palloc.freecount == 0) {
.
67c
	int hw, i, dontalloc;
.
## diffname port/page.c 1992/0905
## diff -e /n/bootesdump/1992/0805/sys/src/9/port/page.c /n/bootesdump/1992/0905/sys/src/9/port/page.c
240c
	if(np->ref != 0) {			/* Stolen by lookpage */
.
187a
	if(pg->ref != 1)
		panic("simpleputpage");
.
115,118c
	if(p->ref != 0) {			/* lookpage has priority on steal */
		unlock(p);
		goto retry;
	}
.
68a
retry:
.
## diffname port/page.c 1992/0910
## diff -e /n/bootesdump/1992/0905/sys/src/9/port/page.c /n/bootesdump/1992/0910/sys/src/9/port/page.c
97c
		 * newpage again when it has reacquired the segment locks
.
## diffname port/page.c 1992/0911
## diff -e /n/bootesdump/1992/0910/sys/src/9/port/page.c /n/bootesdump/1992/0911/sys/src/9/port/page.c
58,59c
/*	print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n", 
	palloc.user, pmem, vmem, hw/1024, hr/1024);/**/
.
## diffname port/page.c 1992/0913
## diff -e /n/bootesdump/1992/0911/sys/src/9/port/page.c /n/bootesdump/1992/0913/sys/src/9/port/page.c
58c
	print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n", 
.
## diffname port/page.c 1992/1209
## diff -e /n/bootesdump/1992/0913/sys/src/9/port/page.c /n/bootesdump/1992/1209/sys/src/9/port/page.c
329c
	for(f = pghash(daddr); f; f = f->hash) {
.
312c
	l = &pghash(daddr);
.
300c
	l = &pghash(p->daddr);
.
296a
	/* If this ever happens it should be fixed by calling
	 * uncachepage instead of panic. I think there is a race
	 * with pio in which this can happen. Calling uncachepage is
	 * correct - I just wanted to see if we got here.
	 */
	if(p->image)
		panic("cachepage");

.
279c
	l = &pghash(p->daddr);
.
271c
uncachepage(Page *p)			/* Always called with a locked page */
.
229c
	if(palloc.tail) {		/* Link back onto tail to give us lru */
.
223,224c
	np = palloc.head;		/* Allocate a new page from freelist */
	if(palloc.head = np->next)	/* = Assign */
.
180c
		palloc.freecount++;	/* Release people waiting for memory */
.
116c
	if(p->ref != 0) {	/* lookpage has priority on steal */
.
8,9c
#define	pghash(daddr)	palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)]
.
## diffname port/page.c 1993/0116
## diff -e /n/bootesdump/1992/1209/sys/src/9/port/page.c /n/bootesdump/1993/0116/sys/src/9/port/page.c
250a
	mmunewpage(np);
.
124a
	mmunewpage(p);
.
## diffname port/page.c 1993/0210
## diff -e /n/bootesdump/1993/0116/sys/src/9/port/page.c /n/bootesdump/1993/0210/sys/src/9/port/page.c
419a
			break;
		}
		for(pg = p->pages; pg < ptop; pg++) {
			pt = *pg;
			if(pt == 0) 
				continue;
			lock(pt);
			ref = --pt->ref;
			unlock(pt);
			if(ref == 0)
				free(pt);
		}
.
415,417c
		if(fn) {
			for(pg = p->pages; pg < ptop; pg++) {
				if(*pg == 0)
					continue;
				(*fn)(*pg);
.
413a
		fn = s->pseg->pgfree;
.
410c
	int ref;
	Page *pt, **pg, **ptop;
	void (*fn)(Page*);
.
## diffname port/page.c 1993/0501
## diff -e /n/bootesdump/1993/0210/sys/src/9/port/page.c /n/fornaxdump/1993/0501/sys/src/brazil/port/page.c
412a
	Page *pt, **pg, **ptop;
.
411d
252c
	for(i = 0; i < MAXMACH; i++)
		np->cachectl[i] |= PG_DATINVALID;
.
207a
	int i;
.
123,125c
	memset(p->cachectl, PG_DATINVALID, sizeof(p->cachectl));
.
72c
	while((palloc.freecount < hw && up->kp == 0) || palloc.freecount == 0) {
.
66c
	int hw, dontalloc;
.
54,58c
	print("%lud free pages\n%dK bytes\n%dK swap\n", palloc.user, pmem, vmem);
.
17c
	ulong np, vmem, pmem;
.
## diffname port/page.c 1993/0810
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/page.c /n/fornaxdump/1993/0810/sys/src/brazil/port/page.c
192,195c

	palloc.freecount++;	/* Release people waiting for memory */
	unlock(&palloc);
	unlock(p);
.
177,190c
	else {
		if(palloc.head) {
			p->next = palloc.head;
			palloc.head->prev = p;
		}
		else {
			palloc.tail = p;
			p->next = 0;
		}
		palloc.head = p;
		p->prev = 0;
.
173,175c
		palloc.tail = p;
		p->next = 0;
.
162,169d
147,159c
	if(--p->ref > 0) {
		unlock(p);
		return;
	}
	vcacheinval(p);
	lock(&palloc);
	if(p->image && p->image != &swapimage) {
		if(palloc.tail) {
			p->prev = palloc.tail;
			palloc.tail->next = p;
.
122c
	if(clear) {
.
90,92c
		 * If called from fault and we lost the segment from
		 * underneath don't waste time allocating and freeing 
		 * a page. Fault will call newpage again when it has 
		 * reacquired the segment locks
.
79c
		while(waserror())	/* Ignore interrupts */
.
77c
		qlock(&palloc.pwait);	/* Hold memory requesters here */
.
68c
	fc = palloc.freecount;
	while((fc < hw && up->kp == 0) || fc == 0) {
.
62c
	int hw, dontalloc, fc;
.
## diffname port/page.c 1993/0811
## diff -e /n/fornaxdump/1993/0810/sys/src/brazil/port/page.c /n/fornaxdump/1993/0811/sys/src/brazil/port/page.c
234,235d
189d
152a

.
121c
	for(i = 0; i < MAXMACH; i++)
		p->cachectl[i] = PG_NOFLUSH;
.
62c
	int i, hw, dontalloc, fc;
.
## diffname port/page.c 1993/0815
## diff -e /n/fornaxdump/1993/0811/sys/src/brazil/port/page.c /n/fornaxdump/1993/0815/sys/src/brazil/port/page.c
155c
	vcacheinval(p, p->va);
.
## diffname port/page.c 1993/0816
## diff -e /n/fornaxdump/1993/0815/sys/src/brazil/port/page.c /n/fornaxdump/1993/0816/sys/src/brazil/port/page.c
230a
if(np->log == 0) {
	np->log = smalloc(8192);
	np->lptr = 0;
}
.
116a

if(p->log == 0) {
	p->log = smalloc(8192);
	p->lptr = 0;
}

.
## diffname port/page.c 1993/0817
## diff -e /n/fornaxdump/1993/0816/sys/src/brazil/port/page.c /n/fornaxdump/1993/0817/sys/src/brazil/port/page.c
351a
				palloc.freecol[f->color]--;
.
217a
	if(np->next)
		np->next->prev = np->prev;
	else
		palloc.tail = np->prev;

.
216c
		palloc.head = np->next;
.
212,214c
	color = getcolor(p->va);
	for(np = palloc.head; np; np = np->next)
		if(np->color == color)
			break;

	/* No page of the correct color */
	if(np == 0) {
		unlock(&palloc);
		uncachepage(p);	
		return;
	}

	if(np->prev) 
		np->prev->next = np->next;
.
196a
	int color;
.
188a
	palloc.freecol[p->color]++;
	if(palloc.r.p != 0)
		wakeup(&palloc.r);

.
161d
109a
	palloc.freecol[color]--;
.
108a
	if(p->next)
		p->next->prev = p->prev;
	else
		palloc.tail = p->prev;


.
107c
		palloc.head = p->next;
.
103,105c
	for(p = palloc.head; p; p = p->next)
		if(p->color == color)
			break;

	if(p == 0)
		panic("newpage");

	if(p->prev) 
		p->prev->next = p->next;
.
78c
		qlock(&palloc.pwait);	 /* Hold memory requesters here */
.
68,69c
	for(;;) {
		if(palloc.freecol[color] > hw)
			break;
		if(up->kp && palloc.freecol[color] > 0)
			break;

.
66a
	color = getcolor(va);
.
62c
	int i, hw, dontalloc, color;
.
54c
	print("%lud free pages\n%dK bytes\n%dK swap\n", palloc.user, pm, vm);
.
51c
	swapalloc.highwater = (palloc.user*5)/100;
.
46,48c
	pm = palloc.user*BY2PG/1024;
	vm = pm + (conf.nswap*BY2PG)/1024;
.
36a
		p->color = color;
		palloc.freecol[color]++;
		color = (color+1)%NCOLOR;
.
28a
		p->color = color;
		palloc.freecol[color]++;
		color = (color+1)%NCOLOR;
.
23a
	color = 0;
.
17c
	ulong np, vm, pm;
.
15a
	int color;
.
## diffname port/page.c 1993/0818
## diff -e /n/fornaxdump/1993/0817/sys/src/brazil/port/page.c /n/fornaxdump/1993/0818/sys/src/brazil/port/page.c
282,285d
263c
	/* Link back onto tail to give us lru in the free list */
	if(palloc.tail) {
.
143,147d
## diffname port/page.c 1993/0819
## diff -e /n/fornaxdump/1993/0818/sys/src/brazil/port/page.c /n/fornaxdump/1993/0819/sys/src/brazil/port/page.c
365a
return 0;
.
## diffname port/page.c 1993/0825
## diff -e /n/fornaxdump/1993/0819/sys/src/brazil/port/page.c /n/fornaxdump/1993/0825/sys/src/brazil/port/page.c
398a
print("#");
.
366d
## diffname port/page.c 1993/0827
## diff -e /n/fornaxdump/1993/0825/sys/src/brazil/port/page.c /n/fornaxdump/1993/0827/sys/src/brazil/port/page.c
398d
## diffname port/page.c 1993/0906
## diff -e /n/fornaxdump/1993/0827/sys/src/brazil/port/page.c /n/fornaxdump/1993/0906/sys/src/brazil/port/page.c
236c
	color = getpgcolor(p->va);
.
74c
	color = getpgcolor(va);
.
## diffname port/page.c 1993/0910
## diff -e /n/fornaxdump/1993/0906/sys/src/brazil/port/page.c /n/fornaxdump/1993/0910/sys/src/brazil/port/page.c
388c

.
230c
	if(palloc.freecol[p->color] < swapalloc.highwater/NCOLOR) {
.
209,210c
	r = &palloc.r[p->color];
	if(r->p != 0)
		wakeup(r);
.
207d
169a
	Rendez *r;

.
163,164c
	int color;

	color = (int)p;
	return palloc.freecol[color] >= swapalloc.highwater/NCOLOR;
.
133d
100c
		qunlock(&palloc.pwait[color]);
.
96c
		tsleep(&palloc.r[color], ispages, (void*)color, 1000);
.
90c
		qlock(&palloc.pwait[color]); /* Hold memory requesters here */
.
## diffname port/page.c 1993/0918
## diff -e /n/fornaxdump/1993/0910/sys/src/brazil/port/page.c /n/fornaxdump/1993/0918/sys/src/brazil/port/page.c
61c
	print("%lud free pages\n", palloc.user);
	print("%dK bytes\n", pm);
	print("%dK swap\n", vm);
.
## diffname port/page.c 1993/1008
## diff -e /n/fornaxdump/1993/0918/sys/src/brazil/port/page.c /n/fornaxdump/1993/1008/sys/src/brazil/port/page.c
79c
		if(palloc.freecol[color] > hw/NCOLOR)
.
## diffname port/page.c 1993/1015
## diff -e /n/fornaxdump/1993/1008/sys/src/brazil/port/page.c /n/fornaxdump/1993/1015/sys/src/brazil/port/page.c
324a
	p->daddr = 0;
.
220a
Page*
auxpage()
{
	Page *p;

	lock(&palloc);
	p = palloc.head;
	if(palloc.freecol[p->color] < swapalloc.highwater/NCOLOR) {
		unlock(&palloc);
		return 0;
	}
	p->next->prev = 0;
	palloc.head = p->next;
	palloc.freecol[p->color]--;
	unlock(&palloc);

	lock(p);
	if(p->ref != 0) {		/* Stolen by lookpage */
		unlock(p);
		return 0;
	}
	p->ref++;
	uncachepage(p);
	unlock(p);
	return p;
}

.
## diffname port/page.c 1993/1120
## diff -e /n/fornaxdump/1993/1015/sys/src/brazil/port/page.c /n/fornaxdump/1993/1120/sys/src/brazil/port/page.c
422c
				palloc.freecount--;
.
262c
	if(palloc.freecount < swapalloc.highwater) {
.
234c
	palloc.freecount--;
.
228c
	if(palloc.freecount < swapalloc.highwater) {
.
212,215c
	palloc.freecount++;
	if(palloc.r.p != 0)
		wakeup(&palloc.r);
.
173,174d
164,167c
	USED(p);
	return palloc.freecount >= swapalloc.highwater;
.
140a
		print("stolen\n");
		lock(&palloc);
		palloc.freecount++;
.
135c
	palloc.freecount--;
.
121,122c
	if(p == 0) {
		p = palloc.head;
		memset(p->cachectl, PG_DATFLUSH, sizeof(p->cachectl));
		p->color = color;
	}
.
116a
	/* First try for out colour */
.
114d
102c
		qunlock(&palloc.pwait);
.
98c
		tsleep(&palloc.r, ispages, 0, 1000);
.
92c
		qlock(&palloc.pwait);	/* Hold memory requesters here */
.
84d
81c
		if(up->kp && palloc.freecount > 0)
.
79c
		if(palloc.freecount > hw)
.
75a
	lock(&palloc);
retry:
.
73,74d
43c
		palloc.freecount++;
.
32c
		palloc.freecount++;
.
## diffname port/page.c 1993/1211
## diff -e /n/fornaxdump/1993/1120/sys/src/brazil/port/page.c /n/fornaxdump/1993/1211/sys/src/brazil/port/page.c
120a
print("! ");
.
## diffname port/page.c 1993/1212
## diff -e /n/fornaxdump/1993/1211/sys/src/brazil/port/page.c /n/fornaxdump/1993/1212/sys/src/brazil/port/page.c
123c
		memset(p->cachectl, PG_NEWCOL, sizeof(p->cachectl));
.
115c
	/* First try for our colour */
.
## diffname port/page.c 1993/1219
## diff -e /n/fornaxdump/1993/1212/sys/src/brazil/port/page.c /n/fornaxdump/1993/1219/sys/src/brazil/port/page.c
137d
## diffname port/page.c 1994/0508
## diff -e /n/fornaxdump/1993/1219/sys/src/brazil/port/page.c /n/fornaxdump/1994/0508/sys/src/brazil/port/page.c
121d
## diffname port/page.c 1994/0817
## diff -e /n/fornaxdump/1994/0508/sys/src/brazil/port/page.c /n/fornaxdump/1994/0817/sys/src/brazil/port/page.c
336c
	if(p->image == 0 || p->image->notext)
.
257d
253,255c
	/* No dup for swap/cache pages */
	if(p->image->notext)
.
## diffname port/page.c 1994/0819
## diff -e /n/fornaxdump/1994/0817/sys/src/brazil/port/page.c /n/fornaxdump/1994/0819/sys/src/brazil/port/page.c
334c
	if(p->image == 0)
.
## diffname port/page.c 1994/1213
## diff -e /n/fornaxdump/1994/0819/sys/src/brazil/port/page.c /n/fornaxdump/1994/1213/sys/src/brazil/port/page.c
153c
		p->cachectl[i] = ct;
.
123a
		ct = PG_NEWCOL;
.
122d
119a
	ct = PG_NOFLUSH;
.
70a
	uchar ct;
.
## diffname port/page.c 1995/0804
## diff -e /n/fornaxdump/1994/1213/sys/src/brazil/port/page.c /n/fornaxdump/1995/0804/sys/src/brazil/port/page.c
170d
168c
ispages(void*)
.
## diffname port/page.c 1998/0512
## diff -e /n/fornaxdump/1995/0804/sys/src/brazil/port/page.c /n/emeliedump/1998/0512/sys/src/brazil/port/page.c
490c
			if(pt == 0)
.
454c
	return new;
.
425c
			return f;
.
410c
				if(f->prev)
.
308c

.
278c
	if(np->prev)
.
274c
		uncachepage(p);
.
262c
		uncachepage(p);
.
128c
	if(p->prev)
.
106,107c
		 * underneath don't waste time allocating and freeing
		 * a page. Fault will call newpage again when it has
.
## diffname port/page.c 1998/0513
## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/page.c /n/emeliedump/1998/0513/sys/src/brazil/port/page.c
428a

.
424a

.
423d
419d
414d
407,408d
404a
				unlock(&palloc);
.
401a
			lock(&palloc);
.
302,308c
	/* Cache the new version */
.
299a
	lock(np);
.
282d
258c
	/*
	 *  normal lock ordering is to call
	 *  lock(&palloc) before lock(p).
	 *  To avoid deadlock, we have to drop
	 *  our locks and try again.
	 */
	if(!canlock(&palloc)){
		unlock(p);
		if(up)
			sched();
		lock(p);
		goto retry;
	}

.
255c
	if(p->ref == 0 || p->image == nil || p->image->notext)
.
253a
	retries = 0;
retry:
	if(retries++ > 10000)
		panic("duppage");

.
252a
	int retries;
.
244a
	unlock(&palloc);

.
238,241c
	if(p->ref != 0)
		panic("auxpage");
.
235d
218a
	unlock(&palloc);
.
217d
213a

.
212d
187d
183a
		unlock(&palloc);
.
180a
	lock(&palloc);
.
156a
	unlock(&palloc);
.
142,148c
	if(p->ref != 0)
		panic("newpage");
.
139d
137d
132d
76d
## diffname port/page.c 1998/0605
## diff -e /n/emeliedump/1998/0513/sys/src/brazil/port/page.c /n/emeliedump/1998/0605/sys/src/brazil/port/page.c
414,424c
			if(++f->ref == 1)
				pageunchain(f);
.
298,309d
289,296c
	pageunchain(np);
	pagechaintail(np);
.
250c
		panic("duppage %d", retries);
.
248a

.
225,227c
	pageunchain(p);
.
181,205c
	if(p->image && p->image != &swapimage)
		pagechaintail(p);
	else 
		pagechainhead(p);
.
127,135c
	pageunchain(p);
.
74d
65a
static void
pageunchain(Page *p)
{
	if(canlock(&palloc))
		panic("pageunchain");
	if(p->prev)
		p->prev->next = p->next;
	else
		palloc.head = p->next;
	if(p->next)
		p->next->prev = p->prev;
	else
		palloc.tail = p->prev;
	p->prev = p->next = nil;
	palloc.freecount--;
}

void
pagechaintail(Page *p)
{
	if(canlock(&palloc))
		panic("pagechaintail");
	if(palloc.tail) {
		p->prev = palloc.tail;
		palloc.tail->next = p;
	}
	else {
		palloc.head = p;
		p->prev = 0;
	}
	palloc.tail = p;
	p->next = 0;
	palloc.freecount++;
}

void
pagechainhead(Page *p)
{
	if(canlock(&palloc))
		panic("pagechainhead");
	if(palloc.head) {
		p->next = palloc.head;
		palloc.head->prev = p;
	}
	else {
		palloc.tail = p;
		p->next = 0;
	}
	palloc.head = p;
	p->prev = 0;
	palloc.freecount++;
}

.
10d
## diffname port/page.c 1998/0825
## diff -e /n/emeliedump/1998/0605/sys/src/brazil/port/page.c /n/emeliedump/1998/0825/sys/src/brazil/port/page.c
61,62c
	print("%ludK bytes\n", pm);
	print("%ludK swap\n", vm);
.
## diffname port/page.c 1999/0108
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/port/page.c /n/emeliedump/1999/0108/sys/src/brazil/port/page.c
392a
			putimage(f->image);
			f->image = 0;
			f->daddr = 0;
.
276a
	/* No dup for swap/cache pages but we still have to uncache */
	if(p->image->notext){
		uncachepage(p);
		return;
	}

.
273,274c
	/* don't dup pages with no image */
	if(p->ref == 0 || p->image == nil)
.
## diffname port/page.c 1999/0109
## diff -e /n/emeliedump/1999/0108/sys/src/brazil/port/page.c /n/emeliedump/1999/0109/sys/src/brazil/port/page.c
398,401c
			lock(f);
			if(f->image == i && f->daddr == daddr){
				*l = f->hash;
				putimage(f->image);
				f->image = 0;
				f->daddr = 0;
			}
			unlock(f);
.
277,282d
274c
	if(p->ref == 0 || p->image == nil || p->image->notext)
.
217a

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

.
## diffname port/page.c 2001/0110
## diff -e /n/emeliedump/1999/0109/sys/src/brazil/port/page.c /n/emeliedump/2001/0110/sys/src/9/port/page.c
232a
	uncachepage(p);
.
## diffname port/page.c 2001/0218
## diff -e /n/emeliedump/2001/0110/sys/src/9/port/page.c /n/emeliedump/2001/0218/sys/src/9/port/page.c
233d
## diffname port/page.c 2001/0821
## diff -e /n/emeliedump/2001/0218/sys/src/9/port/page.c /n/emeliedump/2001/0821/sys/src/9/port/page.c
60,61c
	print("%lud free pages, ", palloc.user);
	print("%ludK bytes, ", pm);
.
## diffname port/page.c 2003/0405
## diff -e /n/emeliedump/2001/0821/sys/src/9/port/page.c /n/emeliedump/2003/0405/sys/src/9/port/page.c
69c
		panic("pageunchain (palloc %p)", &palloc);
.
## diffname port/page.c 2003/0417
## diff -e /n/emeliedump/2003/0405/sys/src/9/port/page.c /n/emeliedump/2003/0417/sys/src/9/port/page.c
20a
print("pageinit: allocated %p to %p\n", palloc.head, (uchar*)palloc.head+np*sizeof(Page));
.
## diffname port/page.c 2003/0418
## diff -e /n/emeliedump/2003/0417/sys/src/9/port/page.c /n/emeliedump/2003/0418/sys/src/9/port/page.c
180d
## diffname port/page.c 2003/0506
## diff -e /n/emeliedump/2003/0418/sys/src/9/port/page.c /n/emeliedump/2003/0506/sys/src/9/port/page.c
21d
## diffname port/page.c 2003/0507
## diff -e /n/emeliedump/2003/0506/sys/src/9/port/page.c /n/emeliedump/2003/0507/sys/src/9/port/page.c
178a

.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].