Checkpoint. Hand examined the code and made several changes/improvements.

Doesn't crash quite as easily. Still some nagging bugs.
Partial implementation of hashTable. Need to make find use keys and do proper
memory allocation (i.e. from physPages, not new).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1349 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Phipps 2002-10-03 03:42:59 +00:00
parent 63ffaa3ea4
commit a550db6753
11 changed files with 260 additions and 162 deletions

View File

@ -9,8 +9,14 @@
extern vmHeaderBlock *vmBlock;
bool vpageIsLessThan(void *a,void *b)
{
return (((reinterpret_cast<vpage *>(a))->getStartAddress()) < (reinterpret_cast<vpage *>(b))->getStartAddress());
}
area::area(void)
{
vpages.setIsLessThan(vpageIsLessThan);
}
void area::setup (areaManager *myManager)
@ -20,10 +26,10 @@ void area::setup (areaManager *myManager)
//error ("area::setup done setting up new area\n");
}
unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount)
unsigned long area::mapAddressSpecToAddress(addressSpec type,void * req,int pageCount)
{
// We will lock in the callers
unsigned long base;
unsigned long base,requested=(unsigned long)req;
switch (type)
{
case EXACT:
@ -48,92 +54,73 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque
return base;
}
status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset)
{
status_t area::createAreaGuts( char *inName, int pageCount, void **address, addressSpec type, pageState inState, protectType protect, bool inFinalWrite, int fd, size_t offset, area *originalArea=NULL /* For clone only*/)
{
strcpy(name,inName);
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
vpage *newPage;
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
unsigned long base=mapAddressSpecToAddress(type,*address,pageCount);
if (base==0)
return B_ERROR;
for (int i=0;i<pageCount;i++)
{
vnode *newVnode=new (vmBlock->vnodePool->get()) vnode;
newVnode->fd=fd;
newVnode->offset=offset+PAGE_SIZE*i;
newVnode->valid=true;
newPage=new (vmBlock->vpagePool->get()) vpage;
newPage->setup(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
vpages.add(newPage);
// error ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset);
}
state=inState;
start_address=base;
end_address=base+(pageCount*PAGE_SIZE)-1;
*address=(void *)base;
finalWrite=true;
finalWrite=inFinalWrite;
if (!originalArea)
for (int i=0;i<pageCount;i++)
{
newPage=new (vmBlock->vpagePool->get()) vpage;
if (fd)
{
vnode *newVnode=new (vmBlock->vnodePool->get()) vnode;
newVnode->fd=fd;
newVnode->offset=offset+PAGE_SIZE*i;
newVnode->valid=true;
newPage->setup(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
}
else
newPage->setup(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
vpages.add(newPage);
}
else
for (struct node *cur=originalArea->vpages.rock;cur;cur=cur->next)
{
vpage *page=(vpage *)cur;
newPage=new (vmBlock->vpagePool->get()) vpage;
newPage->setup(base,page->getBacking(),page->getPhysPage(),protect,inState);// Cloned area has the same physical page and backing store...
vpages.add(newPage);
base+=PAGE_SIZE;
}
return B_OK;
}
status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset)
{
return createAreaGuts(inName,pageCount,address,type,inState,protect,true,fd,offset);
}
status_t area::createArea(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect)
{
vpage *newPage;
strcpy(name,inName);
state=inState;
finalWrite=false;
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
error ("area::createArea: Locked in createArea\n");
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
if (base==0)
return B_ERROR;
error ("area::createArea: base address = %ld\n",base);
for (int i=0;i<pageCount;i++)
{
//error ("in area::createArea: creating page = %d\n",i);
newPage=new (vmBlock->vpagePool->get()) vpage;
newPage->setup(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
vpages.add(newPage);
}
start_address=base;
end_address=base+(pageCount*PAGE_SIZE)-1;
*address=(void *)base;
error ("area::createArea: unlocked in createArea\n");
return B_OK;
return createAreaGuts(inName,pageCount,address,type,inState,protect,false,0,0);
}
status_t area::cloneArea(area *origArea, char *inName, void **address, addressSpec type,pageState inState,protectType protect)
{
// error ("area::cloneArea: entered\n");
strcpy(name,inName);
int pageCount = origArea->getPageCount();
// error ("area::cloneArea: locked\n");
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
if (base==0)
return B_ERROR;
start_address=base;
// error ("area::cloneArea: base address = %x\n",base);
for (struct node *cur=origArea->vpages.rock;cur;)
if (type==CLONE)
{
vpage *newPage,*page=(vpage *)cur;
// Cloned area has the same physical page and backing store...
newPage=new (vmBlock->vpagePool->get()) vpage;
newPage->setup(base,page->getBacking(),page->getPhysPage(),protect,inState);
vpages.add(newPage);
base+=PAGE_SIZE;
cur=cur->next;
*address=(void *)(origArea->getStartAddress());
type=EXACT;
}
state=inState;
end_address=base+(pageCount*PAGE_SIZE)-1;
*address=(void *)start_address;
finalWrite=false;
// error ("area::cloneArea: unlocked\n");
return B_OK;
if (origArea->getAreaManager()!=manager)
{
origArea->getAreaManager()->lock(); // This is just begging for a deadlock...
status_t retVal = createAreaGuts(inName,origArea->getPageCount(),address,type,inState,protect,false,0,0,origArea);
origArea->getAreaManager()->unlock();
return retVal;
}
else
return createAreaGuts(inName,origArea->getPageCount(),address,type,inState,protect,false,0,0,origArea);
}
void area::freeArea(void)
@ -184,7 +171,6 @@ status_t area::getInfo(area_info *dest)
bool area::contains(void *address)
{
// no need to lock here...
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)));
@ -198,7 +184,7 @@ status_t area::resize(size_t newSize)
return B_OK;
if (newSize>oldSize)
{
int pageCount = (newSize-oldSize) / PAGE_SIZE;
int pageCount = (newSize - oldSize + PAGE_SIZE - 1) / PAGE_SIZE;
vpage *newPage;
for (int i=0;i<pageCount;i++)
{
@ -210,7 +196,7 @@ status_t area::resize(size_t newSize)
}
else
{
int pageCount = (oldSize -newSize) / PAGE_SIZE;
int pageCount = (oldSize - newSize + PAGE_SIZE - 1) / PAGE_SIZE;
vpage *oldPage;
struct node *cur;
for (int i=0;i<pageCount;i++) // This is probably really slow. Adding an "end" to list would be faster.
@ -218,6 +204,8 @@ status_t area::resize(size_t newSize)
for (cur=vpages.rock;cur->next;cur=cur->next); // INTENTIONAL - find the last one;
oldPage=(vpage *)cur;
vpages.remove(cur);
if (finalWrite)
oldPage->flush();
oldPage->cleanup();
vmBlock->vpagePool->put(oldPage);
}
@ -238,7 +226,6 @@ status_t area::setProtection(protectType prot)
vpage *area::findVPage(unsigned long address)
{
// No need to lock here...
for (struct node *cur=vpages.rock;cur;cur=cur->next)
{
vpage *page=(vpage *)cur;
@ -252,7 +239,6 @@ vpage *area::findVPage(unsigned long address)
bool area::fault(void *fault_address, bool writeError) // true = OK, false = panic.
{
// No need to lock here...
vpage *page=findVPage((unsigned long)fault_address);
if (page)
return page->fault(fault_address,writeError);
@ -262,7 +248,6 @@ bool area::fault(void *fault_address, bool writeError) // true = OK, false = pan
char area::getByte(unsigned long address) // This is for testing only
{
// No need to lock here...
vpage *page=findVPage(address);
if (page)
return page->getByte(address,manager);
@ -272,7 +257,6 @@ char area::getByte(unsigned long address) // This is for testing only
void area::setByte(unsigned long address,char value) // This is for testing only
{
// No need to lock here...
vpage *page=findVPage(address);
if (page)
page->setByte(address,value,manager);
@ -280,7 +264,6 @@ void area::setByte(unsigned long address,char value) // This is for testing only
int area::getInt(unsigned long address) // This is for testing only
{
// No need to lock here...
vpage *page=findVPage(address);
if (page)
return page->getInt(address,manager);
@ -290,7 +273,6 @@ int area::getInt(unsigned long address) // This is for testing only
void area::setInt(unsigned long address,int value) // This is for testing only
{
// No need to lock here...
vpage *page=findVPage(address);
if (page)
page->setInt(address,value,manager);
@ -298,7 +280,6 @@ void area::setInt(unsigned long address,int value) // This is for testing only
void area::pager(int desperation)
{
// No need to lock here...
for (struct node *cur=vpages.rock;cur;cur=cur->next)
{
vpage *page=(vpage *)cur;
@ -308,7 +289,6 @@ void area::pager(int desperation)
void area::saver(void)
{
// No need to lock here...
for (struct node *cur=vpages.rock;cur;cur=cur->next)
{
vpage *page=(vpage *)cur;

View File

@ -28,7 +28,8 @@ class area : public node
area(void);
void setup(areaManager *myManager);
bool nameMatch(char *matchName) {return (strcmp(matchName,name)==0);}
unsigned long mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount);
unsigned long mapAddressSpecToAddress(addressSpec type,void *requested,int pageCount);
status_t createAreaGuts( char *inName, int pageCount, void **address, addressSpec type, pageState inState, protectType protect, bool inFinalWrite, int fd, size_t offset, area *originalArea=NULL /* For clone only*/);
status_t createAreaMappingFile(char *name, int pageCount,void **address, addressSpec type,pageState state,protectType protect,int fd,size_t offset);
status_t createArea (char *name, int pageCount,void **address, addressSpec type,pageState state,protectType protect);
status_t cloneArea(area *area, char *inName, void **address, addressSpec type,pageState inState,protectType protect);

View File

@ -71,8 +71,8 @@ area *areaManager::findAreaLock(void *address)
area *areaManager::findArea(char *address)
{
error ("Finding area by string\n");
lock();
area *retVal=NULL;
lock();
for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next)
{
area *myArea=(area *)cur;
@ -125,13 +125,13 @@ bool areaManager::fault(void *fault_address, bool writeError) // true = OK, fals
area *myArea;
bool retVal;
error ("Faulting \n");
lock();
// lock(); // Normally this should occur, but since we will be locked when we read/write anyway...
myArea=findArea(fault_address);
if (myArea)
retVal= myArea->fault(fault_address,writeError);
else
retVal= false;
unlock();
// unlock();
return retVal;
}
@ -185,11 +185,13 @@ char areaManager::getByte(unsigned long address)
{
area *myArea;
int retVal;
lock();
myArea=findArea((void *)address);
if (myArea)
retVal=myArea->getByte(address);
else
retVal= 0;
unlock();
return retVal;
}
@ -197,28 +199,34 @@ int areaManager::getInt(unsigned long address)
{
area *myArea;
int retVal;
lock();
myArea=findArea((void *)address);
if (myArea)
retVal=myArea->getInt(address);
else
retVal= 0;
unlock();
return retVal;
}
void areaManager::setByte(unsigned long address,char value)
{
area *myArea;
lock();
myArea=findArea((void *)address);
if (myArea)
myArea->setByte(address,value);
unlock();
}
void areaManager::setInt(unsigned long address,int value)
{
area *myArea;
lock();
myArea=findArea((void *)address);
if (myArea)
myArea->setInt(address,value);
unlock();
}
void areaManager::pager(int desperation)
@ -275,3 +283,24 @@ void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off
unlock();
return addr;
}
status_t areaManager::munmap(void *addr,size_t len)
{
// Note that this is broken for any and all munmaps that are not full area in size. This is an all or nothing game...
status_t retVal=B_OK;
lock();
area *myArea=findArea(addr);
if (myArea)
{
removeArea(myArea);
myArea->freeArea();
vmBlock->areaPool->put(myArea);
}
else
{
error ("areaManager::munmap: unable to find requested area\n");
retVal=B_ERROR;
}
unlock();
return retVal;
}

View File

@ -87,25 +87,10 @@ class areaManager // One of these per process
int createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) ;
void pager(int desperation);
void saver(void);
void lock()
{
static long lockCount=0;
if (!((lockCount++)%200))
error ("locking\n");
acquire_sem(myLock);
}
void unlock() {/*error ("unlocking\n");*/release_sem(myLock);}
void lock() { acquire_sem(myLock); }
void unlock() {release_sem(myLock);}
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
status_t munmap(void *addr,size_t len)
{
// Note that this is broken for any and all munmaps that are not full area in size. This is an all or nothing game...
status_t retVal=B_OK;
lock();
int area=findArea(addr)->getAreaID();
if (area) freeArea(area);
unlock();
return retVal;
}
status_t munmap(void *addr,size_t len);
int cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType=ANY, pageState state=NO_LOCK, protectType prot=writable);
bool fault(void *fault_address, bool writeError); // true = OK, false = panic.

View File

@ -0,0 +1,64 @@
#ifndef _HASH_H
#define _HASH_H
#include "list.h"
static bool throwException (node &foo)
{ throw ("Attempting to use an hash table without setting up a 'hash' function"); }
class hashTable : public list
{
public:
hashTable(int size)
{
nodeCount=0;
numRocks=size;
int pageCount=PAGE_SIZE*size/sizeof(list);
page *newPage=vmBlock->pageMan->getPage();
if (!newPage)
throw ("Out of pages to allocate a pool!");
int newCount=PAGE_SIZE/sizeof(area);
acquire_sem(inUse);
//error ("poolarea::get: Adding %d new elements to the pool!\n",newCount);
for (int i=0;i<newCount;i++)
unused.add(((node *)(newPage->getAddress()+(i*sizeof(area)))));
release_sem(inUse);
}
void setHash (ulong (*hash_in)(node &)) { hash=hash_in; }
void setIsEqual (ulong (*isEqual_in)(node &,node &)) { isEqual=isEqual_in; }
int count(void) {return nodeCount;}
void add (node *newNode) {
unsigned long hashValue=hash(*newNode)%numRocks;
// Note - no looking for duplicates; no ordering.
rocks[hashValue].add(newNode);
}
node *next(void) { return NULL; // This operation doesn't make sense for this class}
void remove(node *toNuke)
{
unsigned long hashValue=hash(*findNode)%numRocks;
rocks[hashValue].remove(newNode);
}
void dump(void)
{
for (int i=0;i<numRocks;i++)
for (struct node *cur=rocks[hashValue].rock;cur && !done;cur=cur->next)
error ("hashTable::dump: At %p, next = %p\n",cur,cur->next);
}
node *find(node *findNode)
{
unsigned long hashValue=hash(*findNode)%numRocks;
for (struct node *cur=rocks[hashValue].rock;cur && !done;cur=cur->next)
if (isEqual(*findNode,*cur))
return cur;
return NULL;
}
private:
ulong (*hash)(node &a);
bool (*isEqual)(node &a,node &b);
list *rocks;
int numRocks;
};
#endif

View File

@ -54,7 +54,7 @@ page *pageManager::getPage(void)
release_sem(cleanLock);
//error ("pageManager::getPage:unlocked clean\n");
} // This could fail if someone swooped in and stole our page.
else if (unused.count())
if (!ret && unused.count())
{
//error ("pageManager::getPage:Checking unused\n");
acquire_sem(unusedLock);
@ -76,7 +76,7 @@ page *pageManager::getPage(void)
void pageManager::freePage(page *toFree)
{
error ("Inside freePage; old value = %d",toFree->count);
error ("pageManager::freePage; old value = %d\n",toFree->count);
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);
@ -86,25 +86,28 @@ void pageManager::freePage(page *toFree)
unused.add(toFree);
release_sem(unusedLock);
}
error (" new value = %d, page = %x\n",toFree->count,toFree->getAddress());
error ("pageManager::freePage:new value = %d, page = %x\n",toFree->count,toFree->getAddress());
}
void pageManager::cleaner(void)
{
while (1)
{
snooze(250000);
if (unused.count())
{
//error ("pageManager::cleaner: About to vacuum a page\n");
acquire_sem(unusedLock);
page *first=(page *)unused.next();
release_sem(unusedLock);
first->zero();
acquire_sem(cleanLock);
clean.add(first);
release_sem(cleanLock);
if (first)
{
first->zero();
acquire_sem(cleanLock);
clean.add(first);
release_sem(cleanLock);
}
//error ("pageManager::cleaner: All done with vacuum a page\n");
snooze(125000);
}
}
}
@ -119,13 +122,16 @@ int pageManager::desperation(void)
void pageManager::dump(void)
{
error ("Dumping the unused list\n");
acquire_sem(unusedLock);
for (struct node *cur=unused.rock;cur;)
{
page *thisPage=(page *)cur;
thisPage->dump();
cur=cur->next;
}
release_sem(unusedLock);
error ("Dumping the clean list\n");
acquire_sem(cleanLock);
for (struct node *cur=clean.rock;cur;)
{
page *thisPage=(page *)cur;
@ -133,10 +139,13 @@ void pageManager::dump(void)
cur=cur->next;
}
error ("Dumping the inuse list\n");
release_sem(cleanLock);
acquire_sem(inUseLock);
for (struct node *cur=inUse.rock;cur;)
{
page *thisPage=(page *)cur;
thisPage->dump();
cur=cur->next;
}
release_sem(inUseLock);
}

View File

@ -16,26 +16,6 @@ swapFileManager::swapFileManager(void)
lockFreeList=create_sem(1,"SwapFile Free List Semaphore"); // Should have team name in it.
}
void swapFileManager::write_block(vnode &node,void *loc,unsigned long size)
{
//error ("swapFileManager::write_block: writing, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc);
if (-1==lseek(node.fd,node.offset,SEEK_SET))
error ("seek failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno));
if (-1==write(node.fd,loc,size))
error ("Write failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno));
node.valid=true;
//error ("swapFileManager::write_block: done, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc);
}
void swapFileManager::read_block(vnode &node,void *loc,unsigned long size)
{
if (node.valid==false)
return; // Do nothing. This prevents "garbage" data on disk from being read in...
//error ("swapFileManager::read_block: reading, node.fd = %d, node.offset = %d into %x\n",node.fd, node.offset,loc);
lseek(node.fd,node.offset,SEEK_SET);
read(node.fd,loc,size);
}
vnode &swapFileManager::findNode(void)
{
//error ("swapFileManager::findNode: Entering findNode \n");
@ -43,10 +23,10 @@ vnode &swapFileManager::findNode(void)
//error ("swapFileManager::findNode: Finding a new node for you, Master: ");
vnode *newNode;
//error ("locking in sfm\n");
Lock();
lock();
newNode=reinterpret_cast<vnode *>(swapFileFreeList.next());
//error ("unlocking in sfm\n");
Unlock();
unlock();
if (!newNode)
{
newNode=new (vmBlock->vnodePool->get()) vnode;
@ -63,15 +43,14 @@ vnode &swapFileManager::findNode(void)
void swapFileManager::freeVNode(vnode &v)
{
v.count--;
if (v.count==0)
if ( atomic_add(&v.count,-1)==1)
{
//error ("locking in sfm\n");
Lock();
lock();
//error ("swapFileManager::freeNode: Starting Freeing a new node for you, Master: offset:%d\n",v.offset);
v.valid=false;
swapFileFreeList.add(&v);
//error ("unlocking in sfm\n");
Unlock();
unlock();
}
}

View File

@ -18,7 +18,8 @@ class swapFileManager {
void freeVNode(vnode &); // Free a node
void write_block(vnode &node,void *loc,unsigned long size);
void read_block(vnode &node,void *loc,unsigned long size);
void Lock() {acquire_sem(lockFreeList);}
void Unlock() {release_sem(lockFreeList);}
void lock() {acquire_sem(lockFreeList);}
void unlock() {release_sem(lockFreeList);}
int getFD(void) {return swapFile;}
};
#endif

View File

@ -71,6 +71,7 @@ struct loopTestParameters
int32 loopTest(void *parameters)
{
try{
error ("Starting Loop Test!\n");
loopTestParameters *params=((loopTestParameters *)parameters);
int area1;
@ -86,6 +87,12 @@ int32 loopTest(void *parameters)
snooze(params->loopSnooze);
}
}
catch (...)
{
error ("Exception thrown!\n");
exit(1);
}
}
int32 getInfoTest(void *parameters)
{
@ -93,6 +100,7 @@ int32 getInfoTest(void *parameters)
area_info ai;
int area1;
try{
while (1)
{
snooze(params->initialSnooze);
@ -117,9 +125,16 @@ int32 getInfoTest(void *parameters)
snooze(params->loopSnooze);
}
}
catch (...)
{
error ("Exception thrown!\n");
exit(1);
}
}
int32 mmapTest (void *parameters)
{
try{
void *map;
loopTestParameters *params=((loopTestParameters *)parameters);
int size=params->areaSize; // Note that this is in bytes, not in pages
@ -145,13 +160,19 @@ int32 mmapTest (void *parameters)
error ("Closed file, fd = %d\n",fd);
}
}
catch (...)
{
error ("Exception thrown!\n");
exit(1);
}
}
int32 cloneTest (void *parameters)
{
loopTestParameters *params=((loopTestParameters *)parameters);
int area1,area2;
void *cloneAddr=NULL;
try {
while (1)
{
snooze(params->initialSnooze);
@ -170,6 +191,12 @@ int32 cloneTest (void *parameters)
snooze(params->loopSnooze);
}
}
catch (...)
{
error ("Exception thrown!\n");
exit(1);
}
}
int main(int argc,char **argv)
{
@ -184,8 +211,8 @@ int main(int argc,char **argv)
resume_thread(loop2=spawn_thread(loopTest,"area test 2",0,&area2Params));
resume_thread(loop3=spawn_thread(loopTest,"area test 3",0,&area3Params));
resume_thread(info1=spawn_thread(getInfoTest,"info test 1",0,&info1Params));
resume_thread(mmap1=spawn_thread(mmapTest,"mmap test 1",0,&mmap1Params));
resume_thread(clone1=spawn_thread(cloneTest,"clone test 1",0,&clone1Params));
//resume_thread(mmap1=spawn_thread(mmapTest,"mmap test 1",0,&mmap1Params));
//resume_thread(clone1=spawn_thread(cloneTest,"clone test 1",0,&clone1Params));
snooze(1000000000);

View File

@ -133,7 +133,9 @@ 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 retVal;
error ("vmInterface::createArea: Creating an area!\n");
retVal = getAM()->createArea(AreaName,pageCount,address,addType,state,protect);
error ("vmInterface::createArea: Done creating an area!\n");
return retVal;
}
@ -145,7 +147,9 @@ void vmInterface::freeArea(int area)
status_t vmInterface::getAreaInfo(int Area,area_info *dest)
{
status_t retVal;
error ("vmInterface::getAreaInfo: Getting info about an area!\n");
retVal = getAM()->getAreaInfo(Area,dest);
error ("vmInterface::getAreaInfo: Done getting info about an area!\n");
return retVal;
}

View File

@ -2,18 +2,35 @@
#include "vnodePool.h"
#include "vmHeaderBlock.h"
#include "areaManager.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
extern vmHeaderBlock *vmBlock;
extern vmHeaderBlock *vmBlock;
void vpage::flush(void)
{
if (protection==writable && dirty)
vmBlock->swapMan->write_block(*backingNode,((void *)(physPage->getAddress())), PAGE_SIZE);
{
//error (vpage::write_block: writing, backingNode->fd = %d, backingNode->offset = %d, address = %x\n",backingNode->fd, backingNode->offset,loc);
if (-1==lseek(backingNode->fd,backingNode->offset,SEEK_SET))
error ("vpage::flush:seek failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno));
if (-1==write(backingNode->fd,(void *)start_address,PAGE_SIZE))
error ("vpage::flush: failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno));
backingNode->valid=true;
//error ("vpage::write_block: done, backingNode->fd = %d, backingNode->offset = %d, address = %x\n",backingNode->fd, backingNode->offset,loc);
}
}
void vpage::refresh(void)
{
vmBlock->swapMan->read_block(*backingNode,((void *)(physPage->getAddress())), PAGE_SIZE);
if (backingNode->valid==false)
return; // Do nothing. This prevents "garbage" data on disk from being read in...
//error ("vpage::refresh: reading, backingNode->fd = %d, backingNode->offset = %d into %x\n",backingNode->fd, backingNode->offset,loc);
if (-1==lseek(backingNode->fd,backingNode->offset,SEEK_SET))
error ("vpage::refresh: seek failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno));
if (-1==read(backingNode->fd,(void *)start_address,PAGE_SIZE))
error ("vpage::refresh: failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno));
}
vpage::vpage(void)
@ -50,7 +67,7 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
atomic_add(&(physMem->count),1);
physPage=physMem;
}
dirty=(physPage!=NULL);
dirty=false;
//error ("vpage::vpage: ended : start = %x, vnode.fd=%d, vnode.offset=%d, physMem = %x\n",start,((backing)?backing->fd:0),((backing)?backing->offset:0), ((physMem)?(physMem->getAddress()):0));
}
@ -61,8 +78,13 @@ void vpage::cleanup(void)
if (backingNode)
{
if (backingNode->fd)
vmBlock->swapMan->freeVNode(*backingNode);
vmBlock->vnodePool->put(backingNode);
if (backingNode->fd==vmBlock->swapMan->getFD())
vmBlock->swapMan->freeVNode(*backingNode);
else
{
if ( atomic_add(&(backingNode->count),-1)==1)
vmBlock->vnodePool->put(backingNode);
}
}
}
@ -75,24 +97,21 @@ void vpage::setProtection(protectType prot)
bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = panic.
{ // This is dispatched by the real interrupt handler, who locates us
error ("vpage::fault: virtual address = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
if (writeError)
if (writeError && physPage)
{
if (physPage)
dirty=true;
if (protection==copyOnWrite) // Else, this was just a "let me know when I am dirty"...
{
dirty=true;
if (protection==copyOnWrite) // Else, this was just a "let me know when I am dirty"...
{
page *newPhysPage=vmBlock->pageMan->getPage();
if (!newPhysPage) // No room at the inn
return false;
memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE);
physPage=newPhysPage;
protection=writable;
backingNode=&(vmBlock->swapMan->findNode()); // Need new backing store for this node, since it was copied, the original is no good...
// Update the architecture specific stuff here...
}
return true;
page *newPhysPage=vmBlock->pageMan->getPage();
if (!newPhysPage) // No room at the inn
return false;
memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE);
physPage=newPhysPage;
protection=writable;
backingNode=&(vmBlock->swapMan->findNode()); // Need new backing store for this node, since it was copied, the original is no good...
// Update the architecture specific stuff here...
}
return true;
}
physPage=vmBlock->pageMan->getPage();
if (!physPage) // No room at the inn
@ -102,7 +121,7 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa
// This refresh is unneeded if the data was never written out...
dump();
refresh(); // I wonder if these vnode calls are safe during an interrupt...
dirty=true;
dirty=false;
error ("vpage::fault: Refreshed\n");
dump();
error ("vpage::fault: exiting\n");