2011-03-30 12:46:40 +00:00
|
|
|
#include "u.h"
|
|
|
|
#include "../port/lib.h"
|
|
|
|
#include "mem.h"
|
|
|
|
#include "dat.h"
|
|
|
|
#include "fns.h"
|
|
|
|
#include "../port/error.h"
|
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
Palloc palloc;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
pageinit(void)
|
|
|
|
{
|
|
|
|
int color, i, j;
|
|
|
|
Page *p;
|
|
|
|
Pallocmem *pm;
|
2014-04-15 19:34:41 +00:00
|
|
|
vlong m, v, u;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2014-06-01 01:13:58 +00:00
|
|
|
if(palloc.pages == nil){
|
|
|
|
ulong np;
|
|
|
|
|
|
|
|
np = 0;
|
|
|
|
for(i=0; i<nelem(palloc.mem); i++){
|
|
|
|
pm = &palloc.mem[i];
|
|
|
|
np += pm->npage;
|
|
|
|
}
|
|
|
|
palloc.pages = xalloc(np*sizeof(Page));
|
|
|
|
if(palloc.pages == nil)
|
|
|
|
panic("pageinit");
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
color = 0;
|
2014-06-22 13:12:45 +00:00
|
|
|
palloc.head = nil;
|
|
|
|
p = palloc.pages;
|
2011-03-30 12:46:40 +00:00
|
|
|
for(i=0; i<nelem(palloc.mem); i++){
|
|
|
|
pm = &palloc.mem[i];
|
|
|
|
for(j=0; j<pm->npage; j++){
|
2014-06-01 01:13:58 +00:00
|
|
|
memset(p, 0, sizeof *p);
|
2011-03-30 12:46:40 +00:00
|
|
|
p->pa = pm->base+j*BY2PG;
|
|
|
|
p->color = color;
|
|
|
|
color = (color+1)%NCOLOR;
|
2014-06-22 13:12:45 +00:00
|
|
|
pagechainhead(p);
|
2011-03-30 12:46:40 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
palloc.user = p - palloc.pages;
|
2014-04-15 19:34:41 +00:00
|
|
|
u = palloc.user*BY2PG;
|
|
|
|
v = u + conf.nswap*BY2PG;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
/* Paging numbers */
|
|
|
|
swapalloc.highwater = (palloc.user*5)/100;
|
|
|
|
swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);
|
|
|
|
|
|
|
|
m = 0;
|
|
|
|
for(i=0; i<nelem(conf.mem); i++)
|
|
|
|
if(conf.mem[i].npage)
|
|
|
|
m += conf.mem[i].npage*BY2PG;
|
2014-04-15 19:34:41 +00:00
|
|
|
m += PGROUND(end - (char*)KTZERO);
|
|
|
|
|
|
|
|
print("%lldM memory: ", (m+1024*1024-1)/(1024*1024));
|
|
|
|
print("%lldM kernel data, ", (m-u+1024*1024-1)/(1024*1024));
|
|
|
|
print("%lldM user, ", u/(1024*1024));
|
|
|
|
print("%lldM swap\n", v/(1024*1024));
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
2014-02-24 21:42:22 +00:00
|
|
|
void
|
2014-06-22 13:12:45 +00:00
|
|
|
pagechainhead(Page *p)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2014-06-22 13:12:45 +00:00
|
|
|
p->next = palloc.head;
|
|
|
|
palloc.head = p;
|
|
|
|
palloc.freecount++;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
static void
|
|
|
|
freepages(Page *head, Page *tail, int n)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2014-06-22 13:12:45 +00:00
|
|
|
lock(&palloc);
|
|
|
|
tail->next = palloc.head;
|
|
|
|
palloc.head = head;
|
|
|
|
palloc.freecount += n;
|
|
|
|
if(palloc.r.p != nil)
|
|
|
|
wakeup(&palloc.r);
|
|
|
|
unlock(&palloc);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
int
|
|
|
|
pagereclaim(Image *i, int min)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2014-06-22 13:12:45 +00:00
|
|
|
Page **h, **l, *p;
|
|
|
|
Page *fh, *ft;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
lock(i);
|
|
|
|
if(i->pgref == 0){
|
|
|
|
unlock(i);
|
|
|
|
return 0;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2014-06-22 13:12:45 +00:00
|
|
|
incref(i);
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
fh = ft = nil;
|
|
|
|
for(h = i->pghash; h < &i->pghash[PGHSIZE]; h++){
|
|
|
|
if((p = *h) == nil)
|
|
|
|
continue;
|
|
|
|
for(l = h; p != nil; p = p->next){
|
|
|
|
if(p->ref == 0)
|
|
|
|
break;
|
|
|
|
l = &p->next;
|
|
|
|
}
|
|
|
|
if(p == nil)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
*l = p->next;
|
|
|
|
p->next = nil;
|
|
|
|
p->image = nil;
|
|
|
|
p->daddr = ~0;
|
|
|
|
i->pgref--;
|
|
|
|
decref(i);
|
|
|
|
|
|
|
|
if(fh == nil)
|
|
|
|
fh = p;
|
|
|
|
else
|
|
|
|
ft->next = p;
|
|
|
|
ft = p;
|
|
|
|
if(++n >= min)
|
|
|
|
break;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2014-06-22 13:12:45 +00:00
|
|
|
unlock(i);
|
|
|
|
putimage(i);
|
|
|
|
|
|
|
|
if(n > 0)
|
|
|
|
freepages(fh, ft, n);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ispages(void*)
|
|
|
|
{
|
|
|
|
return palloc.freecount >= swapalloc.highwater;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Page*
|
2014-01-19 23:47:55 +00:00
|
|
|
newpage(int clear, Segment **s, uintptr va)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2014-06-22 13:12:45 +00:00
|
|
|
Page *p, **l;
|
2011-03-30 12:46:40 +00:00
|
|
|
KMap *k;
|
|
|
|
uchar ct;
|
2014-06-22 13:12:45 +00:00
|
|
|
int i, color;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
color = getpgcolor(va);
|
2014-06-22 13:12:45 +00:00
|
|
|
lock(&palloc);
|
2011-03-30 12:46:40 +00:00
|
|
|
for(;;) {
|
2014-06-22 13:12:45 +00:00
|
|
|
if(palloc.freecount > swapalloc.highwater)
|
2011-03-30 12:46:40 +00:00
|
|
|
break;
|
|
|
|
if(up->kp && palloc.freecount > 0)
|
|
|
|
break;
|
|
|
|
unlock(&palloc);
|
2014-06-22 13:12:45 +00:00
|
|
|
if(s != nil)
|
|
|
|
qunlock(*s);
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2011-08-24 12:43:15 +00:00
|
|
|
if(!waserror()){
|
|
|
|
eqlock(&palloc.pwait); /* Hold memory requesters here */
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2011-08-24 12:43:15 +00:00
|
|
|
if(!waserror()){
|
|
|
|
kickpager();
|
|
|
|
tsleep(&palloc.r, ispages, 0, 1000);
|
|
|
|
poperror();
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2011-08-24 12:43:15 +00:00
|
|
|
qunlock(&palloc.pwait);
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2011-08-24 12:43:15 +00:00
|
|
|
poperror();
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
2014-06-22 13:12:45 +00:00
|
|
|
if(s != nil){
|
|
|
|
*s = nil;
|
|
|
|
return nil;
|
2011-08-24 12:43:15 +00:00
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
lock(&palloc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* First try for our colour */
|
2014-06-22 13:12:45 +00:00
|
|
|
l = &palloc.head;
|
|
|
|
for(p = *l; p != nil; p = p->next){
|
2011-03-30 12:46:40 +00:00
|
|
|
if(p->color == color)
|
|
|
|
break;
|
2014-06-22 13:12:45 +00:00
|
|
|
l = &p->next;
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
ct = PG_NOFLUSH;
|
2014-06-22 13:12:45 +00:00
|
|
|
if(p == nil) {
|
|
|
|
l = &palloc.head;
|
|
|
|
p = *l;
|
2011-03-30 12:46:40 +00:00
|
|
|
p->color = color;
|
|
|
|
ct = PG_NEWCOL;
|
|
|
|
}
|
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
*l = p->next;
|
|
|
|
p->next = nil;
|
|
|
|
palloc.freecount--;
|
|
|
|
unlock(&palloc);
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
p->ref = 1;
|
2011-03-30 12:46:40 +00:00
|
|
|
p->va = va;
|
|
|
|
p->modref = 0;
|
|
|
|
for(i = 0; i < MAXMACH; i++)
|
|
|
|
p->cachectl[i] = ct;
|
|
|
|
|
|
|
|
if(clear) {
|
|
|
|
k = kmap(p);
|
|
|
|
memset((void*)VA(k), 0, BY2PG);
|
|
|
|
kunmap(k);
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
putpage(Page *p)
|
|
|
|
{
|
|
|
|
if(onswap(p)) {
|
|
|
|
putswap(p);
|
|
|
|
return;
|
|
|
|
}
|
2014-06-22 13:12:45 +00:00
|
|
|
if(p->image != nil) {
|
|
|
|
decref(p);
|
2011-03-30 12:46:40 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-06-22 13:12:45 +00:00
|
|
|
if(decref(p) == 0)
|
|
|
|
freepages(p, p, 1);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Page*
|
|
|
|
auxpage(void)
|
|
|
|
{
|
|
|
|
Page *p;
|
|
|
|
|
|
|
|
lock(&palloc);
|
|
|
|
p = palloc.head;
|
2014-06-22 13:12:45 +00:00
|
|
|
if(p == nil || palloc.freecount < swapalloc.highwater) {
|
2011-03-30 12:46:40 +00:00
|
|
|
unlock(&palloc);
|
2014-06-22 13:12:45 +00:00
|
|
|
return nil;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2014-06-22 13:12:45 +00:00
|
|
|
palloc.head = p->next;
|
|
|
|
p->next = nil;
|
|
|
|
palloc.freecount--;
|
2011-03-30 12:46:40 +00:00
|
|
|
unlock(&palloc);
|
2014-06-22 13:12:45 +00:00
|
|
|
p->ref = 1;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
copypage(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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-06-22 13:12:45 +00:00
|
|
|
cachepage(Page *p, Image *i)
|
|
|
|
{
|
|
|
|
Page **h;
|
|
|
|
|
|
|
|
lock(i);
|
|
|
|
p->image = i;
|
|
|
|
h = &PGHASH(i, p->daddr);
|
|
|
|
p->next = *h;
|
|
|
|
*h = p;
|
|
|
|
incref(i);
|
|
|
|
i->pgref++;
|
|
|
|
unlock(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
uncachepage(Page *p)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2014-06-22 13:12:45 +00:00
|
|
|
Page **l, *x;
|
2013-11-08 21:31:26 +00:00
|
|
|
Image *i;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2013-11-08 21:31:26 +00:00
|
|
|
i = p->image;
|
2014-06-22 13:12:45 +00:00
|
|
|
if(i == nil)
|
2011-03-30 12:46:40 +00:00
|
|
|
return;
|
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
lock(i);
|
|
|
|
if(p->image != i){
|
|
|
|
unlock(i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
l = &PGHASH(i, p->daddr);
|
|
|
|
for(x = *l; x != nil; x = x->next) {
|
|
|
|
if(x == p){
|
|
|
|
*l = p->next;
|
|
|
|
p->next = nil;
|
|
|
|
p->image = nil;
|
|
|
|
p->daddr = ~0;
|
|
|
|
i->pgref--;
|
|
|
|
unlock(i);
|
|
|
|
putimage(i);
|
|
|
|
return;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2014-06-22 13:12:45 +00:00
|
|
|
l = &x->next;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2013-11-08 21:31:26 +00:00
|
|
|
unlock(i);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
Page*
|
|
|
|
lookpage(Image *i, uintptr daddr)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2014-06-22 13:12:45 +00:00
|
|
|
Page *p;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2013-11-08 21:31:26 +00:00
|
|
|
lock(i);
|
2014-06-22 13:12:45 +00:00
|
|
|
for(p = PGHASH(i, daddr); p != nil; p = p->next) {
|
|
|
|
if(p->daddr == daddr) {
|
|
|
|
incref(p);
|
|
|
|
unlock(i);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
2013-11-08 21:31:26 +00:00
|
|
|
unlock(i);
|
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
return nil;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-01-19 23:47:55 +00:00
|
|
|
cachedel(Image *i, uintptr daddr)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2014-06-22 13:12:45 +00:00
|
|
|
Page *p;
|
2012-10-16 12:12:21 +00:00
|
|
|
|
2014-06-22 13:12:45 +00:00
|
|
|
while((p = lookpage(i, daddr)) != nil){
|
|
|
|
uncachepage(p);
|
|
|
|
putpage(p);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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++)
|
2014-06-22 13:12:45 +00:00
|
|
|
if(*src != nil) {
|
2011-03-30 12:46:40 +00:00
|
|
|
if(onswap(*src))
|
|
|
|
dupswap(*src);
|
2014-06-22 13:12:45 +00:00
|
|
|
else
|
|
|
|
incref(*src);
|
2011-03-30 12:46:40 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
freepte(Segment *s, Pte *p)
|
|
|
|
{
|
|
|
|
void (*fn)(Page*);
|
2014-06-22 13:12:45 +00:00
|
|
|
Page **pg, **ptop;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
switch(s->type&SG_TYPE) {
|
|
|
|
case SG_PHYSICAL:
|
|
|
|
fn = s->pseg->pgfree;
|
|
|
|
ptop = &p->pages[PTEPERTAB];
|
2014-06-22 13:12:45 +00:00
|
|
|
if(fn != nil) {
|
2011-03-30 12:46:40 +00:00
|
|
|
for(pg = p->pages; pg < ptop; pg++) {
|
2014-06-22 13:12:45 +00:00
|
|
|
if(*pg == nil)
|
2011-03-30 12:46:40 +00:00
|
|
|
continue;
|
|
|
|
(*fn)(*pg);
|
2014-06-22 13:12:45 +00:00
|
|
|
*pg = nil;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
for(pg = p->pages; pg < ptop; pg++) {
|
2014-06-22 13:12:45 +00:00
|
|
|
if(*pg != nil) {
|
|
|
|
if(decref(*pg) == 0)
|
|
|
|
free(*pg);
|
|
|
|
*pg = nil;
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
for(pg = p->first; pg <= p->last; pg++)
|
2014-06-22 13:12:45 +00:00
|
|
|
if(*pg != nil) {
|
2011-03-30 12:46:40 +00:00
|
|
|
putpage(*pg);
|
2014-06-22 13:12:45 +00:00
|
|
|
*pg = nil;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
ulong
|
|
|
|
pagenumber(Page *p)
|
|
|
|
{
|
|
|
|
return p-palloc.pages;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
checkpagerefs(void)
|
|
|
|
{
|
|
|
|
int s;
|
|
|
|
ulong i, np, nwrong;
|
|
|
|
ulong *ref;
|
|
|
|
|
|
|
|
np = palloc.user;
|
|
|
|
ref = malloc(np*sizeof ref[0]);
|
|
|
|
if(ref == nil){
|
|
|
|
print("checkpagerefs: out of memory\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This may not be exact if there are other processes
|
|
|
|
* holding refs to pages on their stacks. The hope is
|
|
|
|
* that if you run it on a quiescent system it will still
|
|
|
|
* be useful.
|
|
|
|
*/
|
|
|
|
s = splhi();
|
|
|
|
lock(&palloc);
|
|
|
|
countpagerefs(ref, 0);
|
|
|
|
portcountpagerefs(ref, 0);
|
|
|
|
nwrong = 0;
|
|
|
|
for(i=0; i<np; i++){
|
|
|
|
if(palloc.pages[i].ref != ref[i]){
|
2014-06-22 13:12:45 +00:00
|
|
|
iprint("page %#p ref %ld actual %lud\n",
|
2011-03-30 12:46:40 +00:00
|
|
|
palloc.pages[i].pa, palloc.pages[i].ref, ref[i]);
|
|
|
|
ref[i] = 1;
|
|
|
|
nwrong++;
|
|
|
|
}else
|
|
|
|
ref[i] = 0;
|
|
|
|
}
|
|
|
|
countpagerefs(ref, 1);
|
|
|
|
portcountpagerefs(ref, 1);
|
|
|
|
iprint("%lud mistakes found\n", nwrong);
|
|
|
|
unlock(&palloc);
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
portcountpagerefs(ulong *ref, int print)
|
|
|
|
{
|
|
|
|
ulong i, j, k, ns, n;
|
|
|
|
Page **pg, *entry;
|
|
|
|
Proc *p;
|
|
|
|
Pte *pte;
|
|
|
|
Segment *s;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Pages in segments. s->mark avoids double-counting.
|
|
|
|
*/
|
|
|
|
n = 0;
|
|
|
|
ns = 0;
|
|
|
|
for(i=0; i<conf.nproc; i++){
|
|
|
|
p = proctab(i);
|
|
|
|
for(j=0; j<NSEG; j++){
|
|
|
|
s = p->seg[j];
|
|
|
|
if(s)
|
|
|
|
s->mark = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(i=0; i<conf.nproc; i++){
|
|
|
|
p = proctab(i);
|
|
|
|
for(j=0; j<NSEG; j++){
|
|
|
|
s = p->seg[j];
|
|
|
|
if(s == nil || s->mark++)
|
|
|
|
continue;
|
|
|
|
ns++;
|
|
|
|
for(k=0; k<s->mapsize; k++){
|
|
|
|
pte = s->map[k];
|
|
|
|
if(pte == nil)
|
|
|
|
continue;
|
|
|
|
for(pg = pte->first; pg <= pte->last; pg++){
|
|
|
|
entry = *pg;
|
|
|
|
if(pagedout(entry))
|
|
|
|
continue;
|
|
|
|
if(print){
|
|
|
|
if(ref[pagenumber(entry)])
|
2014-01-19 23:47:55 +00:00
|
|
|
iprint("page %#p in segment %#p\n", entry->pa, s);
|
2011-03-30 12:46:40 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(ref[pagenumber(entry)]++ == 0)
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!print){
|
|
|
|
iprint("%lud pages in %lud segments\n", n, ns);
|
|
|
|
for(i=0; i<conf.nproc; i++){
|
|
|
|
p = proctab(i);
|
|
|
|
for(j=0; j<NSEG; j++){
|
|
|
|
s = p->seg[j];
|
|
|
|
if(s == nil)
|
|
|
|
continue;
|
|
|
|
if(s->ref != s->mark){
|
|
|
|
iprint("segment %#p (used by proc %lud pid %lud) has bad ref count %lud actual %lud\n",
|
|
|
|
s, i, p->pid, s->ref, s->mark);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|