From a550db6753fd37dbc8ff9dac4113fb71474f473d Mon Sep 17 00:00:00 2001 From: Michael Phipps Date: Thu, 3 Oct 2002 03:42:59 +0000 Subject: [PATCH] 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 --- src/kernel/vm2/area.C | 138 +++++++++++++------------------ src/kernel/vm2/area.h | 3 +- src/kernel/vm2/areaManager.C | 35 +++++++- src/kernel/vm2/areaManager.h | 21 +---- src/kernel/vm2/hashTable.h | 64 ++++++++++++++ src/kernel/vm2/pageManager.C | 25 ++++-- src/kernel/vm2/swapFileManager.C | 31 ++----- src/kernel/vm2/swapFileManager.h | 5 +- src/kernel/vm2/test.C | 33 +++++++- src/kernel/vm2/vmInterface.C | 4 + src/kernel/vm2/vpage.C | 63 +++++++++----- 11 files changed, 260 insertions(+), 162 deletions(-) create mode 100644 src/kernel/vm2/hashTable.h diff --git a/src/kernel/vm2/area.C b/src/kernel/vm2/area.C index 03ae8841cd..9f50e47dd7 100644 --- a/src/kernel/vm2/area.C +++ b/src/kernel/vm2/area.C @@ -9,8 +9,14 @@ extern vmHeaderBlock *vmBlock; +bool vpageIsLessThan(void *a,void *b) +{ + return (((reinterpret_cast(a))->getStartAddress()) < (reinterpret_cast(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;ivnodePool->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;ivpagePool->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;ivpagePool->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;inext;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; diff --git a/src/kernel/vm2/area.h b/src/kernel/vm2/area.h index a7922e4b42..abd5349a5d 100644 --- a/src/kernel/vm2/area.h +++ b/src/kernel/vm2/area.h @@ -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); diff --git a/src/kernel/vm2/areaManager.C b/src/kernel/vm2/areaManager.C index 3833a64827..f2b52bff26 100644 --- a/src/kernel/vm2/areaManager.C +++ b/src/kernel/vm2/areaManager.C @@ -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; + } diff --git a/src/kernel/vm2/areaManager.h b/src/kernel/vm2/areaManager.h index 349ece06ba..a34b36db5a 100644 --- a/src/kernel/vm2/areaManager.h +++ b/src/kernel/vm2/areaManager.h @@ -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. diff --git a/src/kernel/vm2/hashTable.h b/src/kernel/vm2/hashTable.h new file mode 100644 index 0000000000..ac0f5d8a1b --- /dev/null +++ b/src/kernel/vm2/hashTable.h @@ -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;igetAddress()+(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;inext) + 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 diff --git a/src/kernel/vm2/pageManager.C b/src/kernel/vm2/pageManager.C index 9f10090254..ce8cc706d4 100644 --- a/src/kernel/vm2/pageManager.C +++ b/src/kernel/vm2/pageManager.C @@ -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); } diff --git a/src/kernel/vm2/swapFileManager.C b/src/kernel/vm2/swapFileManager.C index 09b6bffa9a..eafda48687 100644 --- a/src/kernel/vm2/swapFileManager.C +++ b/src/kernel/vm2/swapFileManager.C @@ -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(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(); } } diff --git a/src/kernel/vm2/swapFileManager.h b/src/kernel/vm2/swapFileManager.h index 1b0331393a..7421c674db 100644 --- a/src/kernel/vm2/swapFileManager.h +++ b/src/kernel/vm2/swapFileManager.h @@ -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 diff --git a/src/kernel/vm2/test.C b/src/kernel/vm2/test.C index d45d25d8a0..734f0faff8 100644 --- a/src/kernel/vm2/test.C +++ b/src/kernel/vm2/test.C @@ -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); diff --git a/src/kernel/vm2/vmInterface.C b/src/kernel/vm2/vmInterface.C index 01546f438e..42e0747d80 100644 --- a/src/kernel/vm2/vmInterface.C +++ b/src/kernel/vm2/vmInterface.C @@ -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; } diff --git a/src/kernel/vm2/vpage.C b/src/kernel/vm2/vpage.C index 1c16b82ef0..07b187ccdd 100644 --- a/src/kernel/vm2/vpage.C +++ b/src/kernel/vm2/vpage.C @@ -2,18 +2,35 @@ #include "vnodePool.h" #include "vmHeaderBlock.h" #include "areaManager.h" +#include +#include +#include - 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");