Files
haiku-beta6/src/kernel/vm2/pageManager.C
T
Michael Phipps d50d9a6a18 More code cleanup. Removing unused variables. Simplifying and shrinking
vpage to be nearly a TLB entry. Final stripping will occur with kernel
integration. More comments.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3042 a95241bf-73f2-0310-859d-f6bbb57e9c96
2003-03-26 04:00:38 +00:00

117 lines
3.5 KiB
C++

#include "pageManager.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Handy function (actually handy for the casting) to add a long to a void *
void *addOffset(void *base,unsigned long offset) {
return (void *)(((unsigned long)base+offset));
}
pageManager::pageManager(void) {
}
// Since all of the physical pages will need page structures, allocate memory off of the top for them. Set up the lists and semaphores.
void pageManager::setup(void *area,int pages) {
// Calculate the number of pages that we will need to hold the page structures
int pageOverhead=((pages*sizeof(page))+(PAGE_SIZE-1))/PAGE_SIZE;
for (int i=0;i<pages-pageOverhead;i++) {
page *newPage=(page *)(addOffset(area,i*sizeof(page)));
error ("Setting up a page object at %x, passing in %x\n",
newPage,
addOffset(area,(i+pageOverhead)*PAGE_SIZE));
newPage->setup(addOffset(area,(i+pageOverhead)*PAGE_SIZE));
unused.add(newPage);
}
totalPages=pages;
//error ("pageManager::setup - %d pages ready to top() and roll\n",unused.count());
}
// Try to get a clean page first. If that fails, get a dirty one and clean it. Loop on this.
page *pageManager::getPage(void) {
page *ret=NULL;
while (!ret)
{
if (clean.count()) {
ret=(page *)clean.next();
} // This could fail if someone swooped in and stole our page.
if (!ret && unused.count()) {
ret=(page *)unused.next();
if (ret)
ret->zero();
} // This could fail if someone swooped in and stole our page.
}
error ("pageManager::getPage - returning page %x (phys address %x), clean = %d, unused = %d, inuse = %x\n",ret,ret->getAddress(),clean.count(),unused.count(),inUse.count());
inUse.add(ret);
ret->count++;
if (!ret)
throw ("Out of physical pages!");
return ret;
}
// Take page from in use list and put it on the unused list
void pageManager::freePage(page *toFree) {
//error ("pageManager::freePage; count = %d, address = %p\n",toFree->count,toFree);
if (atomic_add(&(toFree->count),-1)==1) { // atomic_add returns the *PREVIOUS* value. So we need to check to see if the one we are wasting was the last one.
inUse.remove(toFree);
// inUse.dump();
unused.add(toFree);
// unused.dump();
}
}
// Loop forever cleaning any necessary pages
void pageManager::cleaner(void) {
while (1) {
snooze(250000);
cleanOnePage();
}
}
// Find a page that needs cleaning. Take it from the "unused" list, clean it and put it on the clean list.
void pageManager::cleanOnePage(void) {
if (unused.count()) {
page *first=(page *)unused.next();
if (first) {
first->zero();
clean.add(first);
}
}
}
// Calculate how desperate we are for physical pages; 1 is not desperate at all, 5 is critical.
int pageManager::desperation(void) { // Formula to determine how desperate system is to get pages back...
int percentClean=(unused.count()+clean.count())*100/totalPages;
if (percentClean>30) return 1;
return (35-percentClean)/7;
}
void pageManager::dump(void) {
error ("Dumping the unused list (%d entries)\n",getUnusedCount());
unused.lock();
for (struct node *cur=unused.top();cur;) {
page *thisPage=(page *)cur;
thisPage->dump();
cur=cur->next;
}
unused.unlock();
error ("Dumping the clean list (%d entries)\n",getCleanCount());
clean.lock();
for (struct node *cur=clean.top();cur;) {
page *thisPage=(page *)cur;
thisPage->dump();
cur=cur->next;
}
error ("Dumping the inuse list (%d entries)\n",getInUseCount());
clean.unlock();
inUse.lock();
for (struct node *cur=inUse.top();cur;) {
page *thisPage=(page *)cur;
thisPage->dump();
cur=cur->next;
}
inUse.unlock();
}