Many bug fixes and changes.

Also added "locked list" - a semaphore protected list derived from list.h.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2851 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Phipps 2003-02-27 04:41:44 +00:00
parent 7c9135c008
commit a48062f5fa
18 changed files with 100 additions and 77 deletions

View File

@ -180,42 +180,35 @@ status_t area::getInfo(area_info *dest) {
bool area::contains(const void *address) { bool area::contains(const void *address) {
unsigned long base=(unsigned long)(address); unsigned long base=(unsigned long)(address);
// error ("area::contains: looking for %d in %d -- %d, value = %d\n",base,start_address,end_address, ((start_address<=base) && (end_address>=base))); error ("area::contains: looking for %d in %d -- %d, value = %d\n",base,start_address,end_address, ((start_address<=base) && (end_address>=base)));
return ((start_address<=base) && (base<=end_address)); return ((start_address<=base) && (base<=end_address));
} }
// Resize an area. // Resize an area.
status_t area::resize(size_t newSize) { status_t area::resize(size_t newSize) {
size_t oldSize =end_address-start_address; size_t oldSize =end_address-start_address+1;
// Duh. Nothing to do. // Duh. Nothing to do.
if (newSize==oldSize) if (newSize==oldSize)
return B_OK; return B_OK;
// Grow the area. Figure out how many pages, allocate them and set them up // Grow the area. Figure out how many pages, allocate them and set them up
if (newSize>oldSize) { if (newSize>oldSize) {
int pageCount = (newSize - oldSize + PAGE_SIZE - 1) / PAGE_SIZE; int pageCount = (newSize - oldSize + PAGE_SIZE - 1) / PAGE_SIZE;
error ("Old size = %d, new size = %d, pageCount = %d\n",oldSize,newSize,pageCount);
vpage *newPage; vpage *newPage;
for (int i=0;i<pageCount;i++) { for (int i=0;i<pageCount;i++) {
newPage=new (vmBlock->vpagePool->get()) vpage; newPage=new (vmBlock->vpagePool->get()) vpage;
newPage->setup(end_address+PAGE_SIZE*i-1,NULL,NULL,protection,state); newPage->setup(end_address+PAGE_SIZE*i-1,NULL,NULL,protection,state);
vpages.add(newPage); vpages.add(newPage);
} }
end_address+=start_address+newSize; dump();
} }
else { // Ewww. Shrinking. This is ugly right now. else { // Ewww. Shrinking. This is ugly right now.
int pageCount = (oldSize - newSize + PAGE_SIZE - 1) / PAGE_SIZE; size_t newFinalAddress=start_address+newSize;
vpage *oldPage; vpage *oldPage;
struct node *cur; for (hashIterate hi(vpages);node *cur=hi.get();) {
for (int i=0;i<pageCount;i++) { // This is probably really slow. OTOH, how often do people shrink their allocations? oldPage=reinterpret_cast<vpage *>(cur);
node *max; if (oldPage->getStartAddress() > (reinterpret_cast<void *> (newFinalAddress))) {
void *maxAddress=NULL,*curAddress;
for (hashIterate hi(vpages);node *cur=hi.get();)
if ((curAddress=(reinterpret_cast<vpage *>(cur))->getStartAddress()) > maxAddress) {
maxAddress=curAddress;
max=cur;
}
// Found the right one to removei; waste it, pool it, and move on
oldPage=reinterpret_cast<vpage *>(max);
vpages.remove(cur); vpages.remove(cur);
if (finalWrite) if (finalWrite)
oldPage->flush(); oldPage->flush();
@ -223,6 +216,8 @@ status_t area::resize(size_t newSize) {
vmBlock->vpagePool->put(oldPage); vmBlock->vpagePool->put(oldPage);
} }
} }
}
end_address=start_address+newSize;
return B_OK; return B_OK;
} }
@ -238,6 +233,7 @@ status_t area::setProtection(protectType prot) {
vpage *area::findVPage(unsigned long address) { vpage *area::findVPage(unsigned long address) {
vpage findMe(address); vpage findMe(address);
// error ("area::findVPage: finding %ld\n",address);
return reinterpret_cast <vpage *>(vpages.find(&findMe)); return reinterpret_cast <vpage *>(vpages.find(&findMe));
} }
@ -273,9 +269,12 @@ int area::getInt(unsigned long address) { // This is for testing only
} }
void area::setInt(unsigned long address,int value) { // This is for testing only void area::setInt(unsigned long address,int value) { // This is for testing only
// error ("area::setInt - start\n");
vpage *page=findVPage(address); vpage *page=findVPage(address);
// error ("area::setInt - page = %x\n",page);
if (page) if (page)
page->setInt(address,value,manager); page->setInt(address,value,manager);
// error ("area::setInt - done\n");
} }
// For every one of our vpages, call the vpage's pager // For every one of our vpages, call the vpage's pager

View File

@ -2,7 +2,7 @@
#define _AREA_H #define _AREA_H
#include "OS.h" #include "OS.h"
#include "vm.h" #include "vm.h"
#include "list.h" #include "lockedList.h"
#include "hashTable.h" #include "hashTable.h"
class areaManager; class areaManager;
@ -51,6 +51,7 @@ class area : public node
areaManager *getAreaManager(void) {return manager;} areaManager *getAreaManager(void) {return manager;}
unsigned long getEndAddress(void) {return end_address;} unsigned long getEndAddress(void) {return end_address;}
unsigned long getStartAddress(void) {return start_address;} unsigned long getStartAddress(void) {return start_address;}
const char *getName(void) {return name;}
// Debugging // Debugging
void dump(void); void dump(void);

View File

@ -39,8 +39,9 @@ unsigned long areaManager::getNextAddress(int pages, unsigned long start) {
} }
// Remove the area from our list, put it on the area pool and move on // Remove the area from our list, put it on the area pool and move on
void areaManager::freeArea(area_id areaID) { status_t areaManager::freeArea(area_id areaID) {
//error ("areaManager::freeArea: begin\n"); //error ("areaManager::freeArea: begin\n");
status_t retVal=B_OK;
lock(); lock();
area *oldArea=findArea(areaID); area *oldArea=findArea(areaID);
//error ("areaManager::freeArea: found area %x\n",oldArea); //error ("areaManager::freeArea: found area %x\n",oldArea);
@ -55,9 +56,13 @@ void areaManager::freeArea(area_id areaID) {
// error ("areaManager::freeArea: freeArea complete \n"); // error ("areaManager::freeArea: freeArea complete \n");
vmBlock->areaPool->put(oldArea); vmBlock->areaPool->put(oldArea);
} }
else else {
retVal=B_ERROR;
error ("areaManager::freeArea: unable to find requested area\n"); error ("areaManager::freeArea: unable to find requested area\n");
}
unlock(); unlock();
// error ("areaManager::freeArea: final unlock complete\n");
return retVal;
} }
area *areaManager::findAreaLock(void *address) { area *areaManager::findAreaLock(void *address) {
@ -93,7 +98,7 @@ area *areaManager::findArea(const void *address) {
if (myArea->contains(address)) if (myArea->contains(address))
return myArea; return myArea;
} }
error ("areaManager::findArea is giving up\n"); // error ("areaManager::findArea is giving up\n");
return NULL; return NULL;
} }
@ -137,14 +142,14 @@ long areaManager::nextAreaID=0;
// Create an area; get a new structure, call setup, create the guts, set its ID, add it to our list // Create an area; get a new structure, call setup, create the guts, set its ID, add it to our list
int areaManager::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) { int areaManager::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) {
error ("areaManager::createArea - Creating an area\n"); // error ("areaManager::createArea - Creating an area\n");
lock(); lock();
area *newArea = new (vmBlock->areaPool->get()) area; area *newArea = new (vmBlock->areaPool->get()) area;
error ("areaManager::createArea - got a new area (%p) from the areaPool\n",newArea); // error ("areaManager::createArea - got a new area (%p) from the areaPool\n",newArea);
newArea->setup(this); newArea->setup(this);
error ("areaManager::createArea - setup complete\n"); // error ("areaManager::createArea - setup complete\n");
int retVal = newArea->createArea(AreaName,pageCount,address,addType,state,protect); int retVal = newArea->createArea(AreaName,pageCount,address,addType,state,protect);
error ("areaManager::createArea - new area's createArea called\n"); // error ("areaManager::createArea - new area's createArea called\n");
if (retVal==B_OK) { if (retVal==B_OK) {
atomic_add(&nextAreaID,1); atomic_add(&nextAreaID,1);
newArea->setAreaID(nextAreaID); newArea->setAreaID(nextAreaID);
@ -152,6 +157,7 @@ int areaManager::createArea(char *AreaName,int pageCount,void **address, address
addArea(newArea); addArea(newArea);
//error ("areaManager::createArea - new area added to list\n"); //error ("areaManager::createArea - new area added to list\n");
retVal=newArea->getAreaID(); retVal=newArea->getAreaID();
// error ("areaManager::createArea - getAreaID=%d\n",retVal);
//error ("areaManager::createArea - new area id found\n"); //error ("areaManager::createArea - new area id found\n");
} }
unlock(); unlock();
@ -243,16 +249,21 @@ void areaManager::setByte(unsigned long address,char value) {
} }
void areaManager::setInt(unsigned long address,int value) { void areaManager::setInt(unsigned long address,int value) {
error ("areaManager::setInt starting to set on address %lx, value = %d\n",address,value);
area *myArea; area *myArea;
lock(); lock();
error ("areaManager::setInt locked\n");
myArea=findArea((void *)address); myArea=findArea((void *)address);
error ("areaManager::setInt area %s found\n",((myArea)?"":" not "));
if (myArea) if (myArea)
myArea->setInt(address,value); myArea->setInt(address,value);
else { else {
char temp[1000]; char temp[1000];
sprintf (temp,"Unable to find an area for address %d\n",address); sprintf (temp,"Unable to find an area for address %d\n",address);
unlock();
throw (temp); throw (temp);
} }
error ("areaManager::setInt unlocking\n");
unlock(); unlock();
} }

View File

@ -13,7 +13,7 @@ class areaManager // One of these per process
areaManager (); areaManager ();
void addArea(area *newArea) {areas.add(newArea);} void addArea(area *newArea) {areas.add(newArea);}
void removeArea(area *oldArea) {areas.remove(oldArea); } void removeArea(area *oldArea) {areas.remove(oldArea); }
void freeArea(area_id area); status_t freeArea(area_id area);
int createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) ; int createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) ;
int cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType=ANY, pageState state=NO_LOCK, protectType prot=writable); int cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType=ANY, pageState state=NO_LOCK, protectType prot=writable);

View File

@ -1,5 +1,5 @@
#include <OS.h> #include <OS.h>
#include "list.h" #include "lockedList.h"
class area; class area;
class poolarea class poolarea
{ {

View File

@ -1,4 +1,4 @@
#include <list.h> #include <lockedList.h>
#include <vm.h> #include <vm.h>
#include <vpage.h> #include <vpage.h>
#include <area.h> #include <area.h>

View File

@ -1,6 +1,6 @@
#ifndef _HASH_H #ifndef _HASH_H
#define _HASH_H #define _HASH_H
#include "list.h" #include "lockedList.h"
#include "vm.h" #include "vm.h"
#include "page.h" #include "page.h"
#include "pageManager.h" #include "pageManager.h"

View File

@ -0,0 +1,19 @@
#ifndef _LOCKED_LIST_H
#define _LOCKED_LIST_H
#include <OS.h>
#include <list.h>
class lockedList: public list
{
public:
lockedList(void) {myLock=create_sem(1,"lockedListSem");}
void add(node *newNode) {lock();list::add(newNode);unlock();}
node *next(void) {lock();node *retVal=list::next();unlock();return retVal;}
void remove(node *newNode) {lock();list::remove(newNode);unlock();}
void dump() {lock();list::dump();unlock();}
bool ensureSane(void) {lock();bool retVal=list::ensureSane();unlock();return retVal;}
void lock() { acquire_sem(myLock);}
void unlock() { release_sem(myLock);}
private:
sem_id myLock;
};
#endif

View File

@ -1,7 +1,7 @@
#ifndef _PAGE_H #ifndef _PAGE_H
#define _PAGE_H #define _PAGE_H
#include "vm.h" #include "vm.h"
#include "list.h" #include "lockedList.h"
class page : public node { class page : public node {
private: private:
void *cpuSpecific; void *cpuSpecific;

View File

@ -21,9 +21,6 @@ void pageManager::setup(void *area,int pages) {
unused.add(newPage); unused.add(newPage);
} }
cleanLock=create_sem (1,"clean_lock");
unusedLock=create_sem (1,"unused_lock");
inUseLock=create_sem (1,"inuse_lock");
totalPages=pages; totalPages=pages;
//error ("pageManager::setup - %d pages ready to rock and roll\n",unused.count()); //error ("pageManager::setup - %d pages ready to rock and roll\n",unused.count());
} }
@ -34,22 +31,16 @@ page *pageManager::getPage(void) {
while (!ret) while (!ret)
{ {
if (clean.count()) { if (clean.count()) {
acquire_sem(cleanLock);
ret=(page *)clean.next(); ret=(page *)clean.next();
release_sem(cleanLock);
} // This could fail if someone swooped in and stole our page. } // This could fail if someone swooped in and stole our page.
if (!ret && unused.count()) { if (!ret && unused.count()) {
acquire_sem(unusedLock);
ret=(page *)unused.next(); ret=(page *)unused.next();
release_sem(unusedLock);
if (ret) if (ret)
ret->zero(); ret->zero();
} // This could fail if someone swooped in and stole our page. } // This could fail if someone swooped in and stole our page.
} }
//error ("pageManager::getPage - returning page %x, clean = %d, unused = %d, inuse = %x\n",ret,clean.count(),unused.count(),inUse.count()); //error ("pageManager::getPage - returning page %x, clean = %d, unused = %d, inuse = %x\n",ret,clean.count(),unused.count(),inUse.count());
acquire_sem(inUseLock);
inUse.add(ret); inUse.add(ret);
release_sem(inUseLock);
ret->count++; ret->count++;
if (!ret) if (!ret)
throw ("Out of physical pages!"); throw ("Out of physical pages!");
@ -60,15 +51,11 @@ page *pageManager::getPage(void) {
void pageManager::freePage(page *toFree) { void pageManager::freePage(page *toFree) {
//error ("pageManager::freePage; count = %d, address = %p\n",toFree->count,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. 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.
acquire_sem(inUseLock);
inUse.remove(toFree); inUse.remove(toFree);
// inUse.dump(); // inUse.dump();
release_sem(inUseLock);
acquire_sem(unusedLock);
unused.add(toFree); unused.add(toFree);
// unused.dump(); // unused.dump();
release_sem(unusedLock);
} }
} }
@ -83,14 +70,10 @@ void pageManager::cleaner(void) {
// Find a page that needs cleaning. Take it from the "unused" list, clean it and put it on the clean list. // 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) { void pageManager::cleanOnePage(void) {
if (unused.count()) { if (unused.count()) {
acquire_sem(unusedLock);
page *first=(page *)unused.next(); page *first=(page *)unused.next();
release_sem(unusedLock);
if (first) { if (first) {
first->zero(); first->zero();
acquire_sem(cleanLock);
clean.add(first); clean.add(first);
release_sem(cleanLock);
} }
} }
} }
@ -104,27 +87,27 @@ int pageManager::desperation(void) { // Formula to determine how desperate syste
void pageManager::dump(void) { void pageManager::dump(void) {
error ("Dumping the unused list (%d entries)\n",getUnusedCount()); error ("Dumping the unused list (%d entries)\n",getUnusedCount());
acquire_sem(unusedLock); unused.lock();
for (struct node *cur=unused.rock;cur;) { for (struct node *cur=unused.rock;cur;) {
page *thisPage=(page *)cur; page *thisPage=(page *)cur;
thisPage->dump(); thisPage->dump();
cur=cur->next; cur=cur->next;
} }
release_sem(unusedLock); unused.unlock();
error ("Dumping the clean list (%d entries)\n",getCleanCount()); error ("Dumping the clean list (%d entries)\n",getCleanCount());
acquire_sem(cleanLock); clean.lock();
for (struct node *cur=clean.rock;cur;) { for (struct node *cur=clean.rock;cur;) {
page *thisPage=(page *)cur; page *thisPage=(page *)cur;
thisPage->dump(); thisPage->dump();
cur=cur->next; cur=cur->next;
} }
error ("Dumping the inuse list (%d entries)\n",getInUseCount()); error ("Dumping the inuse list (%d entries)\n",getInUseCount());
release_sem(cleanLock); clean.unlock();
acquire_sem(inUseLock); inUse.lock();
for (struct node *cur=inUse.rock;cur;) { for (struct node *cur=inUse.rock;cur;) {
page *thisPage=(page *)cur; page *thisPage=(page *)cur;
thisPage->dump(); thisPage->dump();
cur=cur->next; cur=cur->next;
} }
release_sem(inUseLock); inUse.unlock();
} }

View File

@ -1,7 +1,7 @@
#ifndef _PAGE_MANAGER_H #ifndef _PAGE_MANAGER_H
#define _PAGE_MANAGER_H #define _PAGE_MANAGER_H
#include "/boot/develop/headers/be/kernel/OS.h" #include "/boot/develop/headers/be/kernel/OS.h"
#include "list.h" #include "lockedList.h"
#include "page.h" #include "page.h"
class pageManager { class pageManager {
@ -28,8 +28,7 @@ class pageManager {
int getUnusedCount(void) {return unused.count();} int getUnusedCount(void) {return unused.count();}
int getInUseCount(void) {return inUse.count();} int getInUseCount(void) {return inUse.count();}
private: private:
list clean,unused,inUse; lockedList clean,unused,inUse;
sem_id cleanLock,unusedLock,inUseLock;
int totalPages; int totalPages;
}; };
#endif #endif

View File

@ -1,4 +1,4 @@
#include "list.h" #include "lockedList.h"
#ifndef _VM_TYPES #ifndef _VM_TYPES
#define _VM_TYPES #define _VM_TYPES

View File

@ -10,7 +10,7 @@ class pageManager;
class swapFileManager; class swapFileManager;
class cacheManager; class cacheManager;
class vnodeManager; class vnodeManager;
class list; class lockedList;
#endif #endif
struct vmHeaderBlock struct vmHeaderBlock
@ -22,7 +22,7 @@ struct vmHeaderBlock
swapFileManager *swapMan; swapFileManager *swapMan;
cacheManager *cacheMan; cacheManager *cacheMan;
vnodeManager *vnodeMan; vnodeManager *vnodeMan;
list areas; lockedList areas;
}; };
#endif #endif

View File

@ -1,5 +1,6 @@
#include <new.h> #include <new.h>
#include "mman.h" #include "mman.h"
#include "lockedList.h"
#include "area.h" #include "area.h"
#include "areaPool.h" #include "areaPool.h"
#include "vpagePool.h" #include "vpagePool.h"
@ -145,7 +146,7 @@ status_t vmInterface::resizeArea(int Area,size_t size)
int vmInterface::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) int vmInterface::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect)
{ {
int retVal; int retVal;
error ("vmInterface::createArea: Creating an area!\n"); // error ("vmInterface::createArea: Creating an area!\n");
if (!AreaName) if (!AreaName)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
if (!address) if (!address)
@ -161,19 +162,20 @@ int vmInterface::createArea(char *AreaName,int pageCount,void **address, address
if (protect>copyOnWrite || protect < none) if (protect>copyOnWrite || protect < none)
return B_BAD_VALUE; return B_BAD_VALUE;
retVal = getAM()->createArea(AreaName,pageCount,address,addType,state,protect); retVal = getAM()->createArea(AreaName,pageCount,address,addType,state,protect);
//error ("vmInterface::createArea: Done creating an area!\n"); // error ("vmInterface::createArea: Done creating an area! ID = %d\n",retVal);
return retVal; return retVal;
} }
void vmInterface::freeArea(int area) status_t vmInterface::delete_area(int area)
{ {
getAM()->freeArea(area); return getAM()->freeArea(area);
} }
status_t vmInterface::getAreaInfo(int Area,area_info *dest) status_t vmInterface::getAreaInfo(int Area,area_info *dest)
{ {
status_t retVal; status_t retVal;
//error ("vmInterface::getAreaInfo: Getting info about an area!\n"); //error ("vmInterface::getAreaInfo: Getting info about an area!\n");
if (!dest) return B_ERROR;
retVal = getAM()->getAreaInfo(Area,dest); retVal = getAM()->getAreaInfo(Area,dest);
//error ("vmInterface::getAreaInfo: Done getting info about an area!\n"); //error ("vmInterface::getAreaInfo: Done getting info about an area!\n");
return retVal; return retVal;
@ -189,8 +191,15 @@ status_t vmInterface::getNextAreaInfo(int process,int32 *cookie,area_info *dest
int vmInterface::getAreaByName(char *name) int vmInterface::getAreaByName(char *name)
{ {
int retVal; int retVal=B_NAME_NOT_FOUND;
retVal = getAM()->getAreaByName(name); vmBlock->areas.lock();
for (struct node *cur=vmBlock->areas.rock;cur && retVal==B_NAME_NOT_FOUND;cur=cur->next) {
area *myArea=(area *)cur;
error ("vmInterface::getAreaByName comapring %s to passed in %s\n",myArea->getName(),name);
if (myArea->nameMatch(name))
retVal=myArea->getAreaID();
}
vmBlock->areas.unlock();
return retVal; return retVal;
} }

View File

@ -11,7 +11,7 @@ class vmInterface // This is the class that "owns" all of the managers.
int createArea(char *AreaName,int pageCount,void **address, int createArea(char *AreaName,int pageCount,void **address,
addressSpec addType=ANY, addressSpec addType=ANY,
pageState state=NO_LOCK,protectType protect=writable); pageState state=NO_LOCK,protectType protect=writable);
void freeArea(int Area); status_t delete_area(int Area);
status_t getAreaInfo(int Area,area_info *dest); status_t getAreaInfo(int Area,area_info *dest);
status_t getNextAreaInfo(int process,int32 *cookie,area_info *dest); status_t getNextAreaInfo(int process,int32 *cookie,area_info *dest);
int getAreaByName(char *name); int getAreaByName(char *name);
@ -40,6 +40,6 @@ class vmInterface // This is the class that "owns" all of the managers.
char getByte(unsigned long offset) {return getAM()->getByte(offset);} // This is for testing only char getByte(unsigned long offset) {return getAM()->getByte(offset);} // This is for testing only
void setByte(unsigned long offset,char value) {getAM()->setByte(offset,value);} // This is for testing only void setByte(unsigned long offset,char value) {getAM()->setByte(offset,value);} // This is for testing only
int getInt(unsigned long offset) {return getAM()->getInt(offset);} // This is for testing only int getInt(unsigned long offset) {return getAM()->getInt(offset);} // This is for testing only
void setInt(unsigned long offset,int value) {getAM()->setByte(offset,value);} // This is for testing only void setInt(unsigned long offset,int value) {getAM()->setInt(offset,value);} // This is for testing only
thread_id tid_cleaner,tid_saver,tid_pager; thread_id tid_cleaner,tid_saver,tid_pager;
}; };

View File

@ -1,5 +1,5 @@
#include <OS.h> #include <OS.h>
#include "list.h" #include "lockedList.h"
class area; class area;
class vnode; class vnode;
class poolvnode class poolvnode

View File

@ -86,7 +86,7 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
// If there is no physical page already and we can't wait to get one, then get one now // If there is no physical page already and we can't wait to get one, then get one now
if (!physPage && (state!=LAZY) && (state!=NO_LOCK)) { if (!physPage && (state!=LAZY) && (state!=NO_LOCK)) {
physPage=vmBlock->pageMan->getPage(); physPage=vmBlock->pageMan->getPage();
error ("vpage::setup, state = %d, allocated page %x\n",state,physPage); // error ("vpage::setup, state = %d, allocated page %x\n",state,physPage);
} }
else { // We either don't need it or we already have it. else { // We either don't need it or we already have it.
if (physPage) if (physPage)
@ -120,14 +120,14 @@ void vpage::setProtection(protectType prot) {
// This is dispatched by the real interrupt handler, who locates us // This is dispatched by the real interrupt handler, who locates us
// true = OK, false = panic. // true = OK, false = panic.
bool vpage::fault(void *fault_address, bool writeError, int &in_count) { bool vpage::fault(void *fault_address, bool writeError, int &in_count) {
// error ("vpage::fault: virtual address = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false")); error ("vpage::fault: virtual address = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
if (writeError && protection != copyOnWrite && protection != writable) if (writeError && protection != copyOnWrite && protection != writable)
return false; return false;
if (writeError && physPage) { // If we already have a page and this is a write, it is either a copy on write or a "dirty" notice if (writeError && physPage) { // If we already have a page and this is a write, it is either a copy on write or a "dirty" notice
dirty=true; dirty=true;
if (protection==copyOnWrite) { // Else, this was just a "let me know when I am dirty"... if (protection==copyOnWrite) { // Else, this was just a "let me know when I am dirty"...
page *newPhysPage=vmBlock->pageMan->getPage(); page *newPhysPage=vmBlock->pageMan->getPage();
// error ("vpage::fault - copy on write allocated page %x\n",newPhysPage); error ("vpage::fault - copy on write allocated page %x\n",newPhysPage);
memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE); memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE);
physPage=newPhysPage; physPage=newPhysPage;
protection=writable; protection=writable;
@ -140,10 +140,10 @@ bool vpage::fault(void *fault_address, bool writeError, int &in_count) {
} }
// Guess this is the real deal. Get a physical page. // Guess this is the real deal. Get a physical page.
physPage=vmBlock->pageMan->getPage(); physPage=vmBlock->pageMan->getPage();
// error ("vpage::fault - regular - allocated page %x\n",physPage); error ("vpage::fault - regular - allocated page %x\n",physPage);
if (!physPage) // No room at the inn if (!physPage) // No room at the inn
return false; return false;
// error ("vpage::fault: New page allocated! new physical address = %x vnode.fd=%d, vnode.offset=%d, \n",physPage->getAddress(),((backingNode)?backingNode->fd:0),((backingNode)?backingNode->offset:0)); error ("vpage::fault: New page allocated! new physical address = %x vnode.fd=%d, vnode.offset=%d, \n",physPage->getAddress(),((backingNode)?backingNode->fd:0),((backingNode)?backingNode->offset:0));
// Update the architecture specific stuff here... // Update the architecture specific stuff here...
// This refresh is unneeded if the data was never written out... // This refresh is unneeded if the data was never written out...
// dump(); // dump();
@ -201,10 +201,12 @@ int vpage::getInt(unsigned long address,areaManager *manager) {
} }
void vpage::setInt(unsigned long address,int value,areaManager *manager) { void vpage::setInt(unsigned long address,int value,areaManager *manager) {
error ("vpage::setInt: here I am!\n");
if (!physPage) if (!physPage)
if (!manager->fault((void *)(address),true)) if (!manager->fault((void *)(address),true))
throw ("vpage::setInt"); throw ("vpage::setInt");
*((int *)(address-start_address+physPage->getAddress()))=value; *((int *)(address-start_address+physPage->getAddress()))=value;
error ("vpage::setInt: leaving!\n");
} }
// Swaps pages out where necessary. // Swaps pages out where necessary.

View File

@ -1,5 +1,5 @@
#include <OS.h> #include <OS.h>
#include "list.h" #include "lockedList.h"
class vpage; class vpage;
class poolvpage class poolvpage
{ {