⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 page.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#define	pghash(daddr)	palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)]struct	Palloc palloc;voidpageinit(void){	int color;	Page *p;	ulong np, vm, pm;	np = palloc.np0+palloc.np1;	palloc.head = xalloc(np*sizeof(Page));	if(palloc.head == 0)		panic("pageinit");	color = 0;	p = palloc.head;	while(palloc.np0 > 0) {		p->prev = p-1;		p->next = p+1;		p->pa = palloc.p0;		p->color = color;		palloc.freecount++;		color = (color+1)%NCOLOR;		palloc.p0 += BY2PG;		palloc.np0--;		p++;	}	while(palloc.np1 > 0) {		p->prev = p-1;		p->next = p+1;		p->pa = palloc.p1;		p->color = color;		palloc.freecount++;		color = (color+1)%NCOLOR;		palloc.p1 += BY2PG;		palloc.np1--;		p++;	}	palloc.tail = p - 1;	palloc.head->prev = 0;	palloc.tail->next = 0;	palloc.user = p - palloc.head;	pm = palloc.user*BY2PG/1024;	vm = pm + (conf.nswap*BY2PG)/1024;	/* Pageing numbers */	swapalloc.highwater = (palloc.user*5)/100;	swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);	print("%lud free pages\n", palloc.user);	print("%ludK bytes\n", pm);	print("%ludK swap\n", vm);}static voidpageunchain(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--;}voidpagechaintail(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++;}voidpagechainhead(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++;}Page*newpage(int clear, Segment **s, ulong va){	Page *p;	KMap *k;	uchar ct;	int i, hw, dontalloc, color;	lock(&palloc);	color = getpgcolor(va);	hw = swapalloc.highwater;	for(;;) {		if(palloc.freecount > hw)			break;		if(up->kp && palloc.freecount > 0)			break;		unlock(&palloc);		dontalloc = 0;		if(s && *s) {			qunlock(&((*s)->lk));			*s = 0;			dontalloc = 1;		}		qlock(&palloc.pwait);	/* Hold memory requesters here */		while(waserror())	/* Ignore interrupts */			;		kickpager();		tsleep(&palloc.r, ispages, 0, 1000);		poperror();		qunlock(&palloc.pwait);		/*		 * 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		 */		if(dontalloc)			return 0;		lock(&palloc);	}	/* First try for our colour */	for(p = palloc.head; p; p = p->next)		if(p->color == color)			break;	ct = PG_NOFLUSH;	if(p == 0) {		p = palloc.head;		p->color = color;		ct = PG_NEWCOL;	}	pageunchain(p);	lock(p);	if(p->ref != 0)		panic("newpage");	uncachepage(p);	p->ref++;	p->va = va;	p->modref = 0;	for(i = 0; i < MAXMACH; i++)		p->cachectl[i] = ct;	unlock(p);	unlock(&palloc);	if(clear) {		k = kmap(p);		memset((void*)VA(k), 0, BY2PG);		kunmap(k);	}	return p;}intispages(void*){	return palloc.freecount >= swapalloc.highwater;}voidputpage(Page *p){	if(onswap(p)) {		putswap(p);		return;	}	lock(&palloc);	lock(p);	if(p->ref == 0)		panic("putpage");	if(--p->ref > 0) {		unlock(p);		unlock(&palloc);		return;	}	if(p->image && p->image != &swapimage)		pagechaintail(p);	else 		pagechainhead(p);	if(palloc.r.p != 0)		wakeup(&palloc.r);	unlock(p);	unlock(&palloc);}Page*auxpage(){	Page *p;	lock(&palloc);	p = palloc.head;	if(palloc.freecount < swapalloc.highwater) {		unlock(&palloc);		return 0;	}	pageunchain(p);	lock(p);	if(p->ref != 0)		panic("auxpage");	p->ref++;	uncachepage(p);	unlock(p);	unlock(&palloc);	return p;}voidduppage(Page *p)				/* Always call with p locked */{	Page *np;	int color;	int retries;	retries = 0;retry:	if(retries++ > 10000)		panic("duppage %d", retries);	/* don't dup pages with no image */	if(p->ref == 0 || p->image == nil || p->image->notext)		return;	/*	 *  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;	}	/* No freelist cache when memory is very low */	if(palloc.freecount < swapalloc.highwater) {		unlock(&palloc);		uncachepage(p);		return;	}	color = getpgcolor(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;	}	pageunchain(np);	pagechaintail(np);	lock(np);	unlock(&palloc);	/* Cache the new version */	uncachepage(np);	np->va = p->va;	np->daddr = p->daddr;	copypage(p, np);	cachepage(np, p->image);	unlock(np);	uncachepage(p);}voidcopypage(Page *f, Page *t){	KMap *ks, *kd;	ks = kmap(f);	kd = kmap(t);	memmove((void*)VA(kd), (void*)VA(ks), BY2PG);	kunmap(ks);	kunmap(kd);}voiduncachepage(Page *p)			/* Always called with a locked page */{	Page **l, *f;	if(p->image == 0)		return;	lock(&palloc.hashlock);	l = &pghash(p->daddr);	for(f = *l; f; f = f->hash) {		if(f == p) {			*l = p->hash;			break;		}		l = &f->hash;	}	unlock(&palloc.hashlock);	putimage(p->image);	p->image = 0;	p->daddr = 0;}voidcachepage(Page *p, Image *i){	Page **l;	/* 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");	incref(i);	lock(&palloc.hashlock);	p->image = i;	l = &pghash(p->daddr);	p->hash = *l;	*l = p;	unlock(&palloc.hashlock);}voidcachedel(Image *i, ulong daddr){	Page *f, **l;	lock(&palloc.hashlock);	l = &pghash(daddr);	for(f = *l; f; f = f->hash) {		if(f->image == i && f->daddr == daddr) {			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;	}	unlock(&palloc.hashlock);}Page *lookpage(Image *i, ulong daddr){	Page *f;	lock(&palloc.hashlock);	for(f = pghash(daddr); f; f = f->hash) {		if(f->image == i && f->daddr == daddr) {			unlock(&palloc.hashlock);			lock(&palloc);			lock(f);			if(f->image != i || f->daddr != daddr) {				unlock(f);				unlock(&palloc);				return 0;			}			if(++f->ref == 1)				pageunchain(f);			unlock(&palloc);			unlock(f);			return f;		}	}	unlock(&palloc.hashlock);	return 0;}Pte*ptecpy(Pte *old){	Pte *new;	Page **src, **dst;	new = ptealloc();	dst = &new->pages[old->first-old->pages];	new->first = dst;	for(src = old->first; src <= old->last; src++, dst++)		if(*src) {			if(onswap(*src))				dupswap(*src);			else {				lock(*src);				(*src)->ref++;				unlock(*src);			}			new->last = dst;			*dst = *src;		}	return new;}Pte*ptealloc(void){	Pte *new;	new = smalloc(sizeof(Pte));	new->first = &new->pages[PTEPERTAB];	new->last = new->pages;	return new;}voidfreepte(Segment *s, Pte *p){	int ref;	void (*fn)(Page*);	Page *pt, **pg, **ptop;	switch(s->type&SG_TYPE) {	case SG_PHYSICAL:		fn = s->pseg->pgfree;		ptop = &p->pages[PTEPERTAB];		if(fn) {			for(pg = p->pages; pg < ptop; pg++) {				if(*pg == 0)					continue;				(*fn)(*pg);				*pg = 0;			}			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);		}		break;	default:		for(pg = p->first; pg <= p->last; pg++)			if(*pg) {				putpage(*pg);				*pg = 0;			}	}	free(p);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -