📄 page.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 + -