From cf7199ba56dbb1c92e7559f3392c0ac0182d9bc7 Mon Sep 17 00:00:00 2001 From: Michael Phipps Date: Fri, 10 Jan 2003 01:09:45 +0000 Subject: [PATCH] Many changes due to enhanced testing. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2396 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/vm2/area.C | 12 ++++++++--- src/kernel/vm2/areaManager.C | 32 ++++++++++++++-------------- src/kernel/vm2/areaPool.C | 2 +- src/kernel/vm2/pageManager.C | 4 ++-- src/kernel/vm2/vm.h | 3 +++ src/kernel/vm2/vmInterface.C | 10 ++++----- src/kernel/vm2/vnodeManager.C | 25 +++++++++++++++++++--- src/kernel/vm2/vnodeManager.h | 4 ++-- src/kernel/vm2/vnodePool.C | 2 +- src/kernel/vm2/vpage.C | 40 +++++++++++++++++++---------------- src/kernel/vm2/vpage.h | 4 +++- src/kernel/vm2/vpagePool.C | 2 +- 12 files changed, 87 insertions(+), 53 deletions(-) diff --git a/src/kernel/vm2/area.C b/src/kernel/vm2/area.C index 9e93367275..617580e5d4 100644 --- a/src/kernel/vm2/area.C +++ b/src/kernel/vm2/area.C @@ -3,6 +3,7 @@ #include "areaManager.h" #include "vpage.h" #include "vnodePool.h" +#include "vnodeManager.h" #include "vpagePool.h" #include "vmHeaderBlock.h" @@ -76,7 +77,8 @@ status_t area::createAreaGuts( char *inName, int pageCount, void **address, addr if (fd) { vnode newVnode; newVnode.fd=fd; - newVnode.offset=offset; + newVnode.offset=offset+i*PAGE_SIZE; + newVnode.valid=true; // vmBlock->vnodeManager->addVNode(newVnode,newPage); newPage->setup(base+PAGE_SIZE*i,&newVnode,NULL,protect,inState,share); } @@ -94,6 +96,7 @@ status_t area::createAreaGuts( char *inName, int pageCount, void **address, addr vpages.add(newPage); base+=PAGE_SIZE; } + error ("Dumping the area's hashtable"); dump(); vmBlock->areas.add(this); return B_OK; @@ -132,14 +135,17 @@ void area::freeArea(void) { for (hashIterate hi(vpages);node *cur=hi.get();) { //error ("area::freeArea: wasting a page: %x\n",cur); vpage *page=reinterpret_cast(cur); - if (finalWrite) + if (finalWrite) { page->flush(); -//error ("area::freeArea: flushed a page \n"); + error ("area::freeArea: flushed page %x\n",page); + } page->cleanup(); //page->next=NULL; vmBlock->vpagePool->put(page); } vpages.~hashTable(); + error ("area::freeArea ----------------------------------------------------------------\n"); + vmBlock->vnodeMan->dump(); //error ("area::freeArea: unlocking \n"); //error ("area::freeArea: ending \n"); } diff --git a/src/kernel/vm2/areaManager.C b/src/kernel/vm2/areaManager.C index 72d3aa2156..9fa407c6f8 100644 --- a/src/kernel/vm2/areaManager.C +++ b/src/kernel/vm2/areaManager.C @@ -40,7 +40,7 @@ unsigned long areaManager::getNextAddress(int pages, unsigned long start) { // Remove the area from our list, put it on the area pool and move on void areaManager::freeArea(area_id areaID) { - error ("areaManager::freeArea: begin\n"); + //error ("areaManager::freeArea: begin\n"); lock(); area *oldArea=findArea(areaID); //error ("areaManager::freeArea: found area %x\n",oldArea); @@ -69,7 +69,7 @@ area *areaManager::findAreaLock(void *address) { // Loops over our areas looking for this one by name area *areaManager::findArea(char *address) { - error ("Finding area by string\n"); + //error ("Finding area by string\n"); area *retVal=NULL; lock(); for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next) @@ -98,7 +98,7 @@ area *areaManager::findArea(const void *address) { } area *areaManager::findAreaLock(area_id id) { - error ("Finding area by areaID \n"); + //error ("Finding area by areaID \n"); lock(); area *retVal=findArea(id); unlock(); @@ -122,7 +122,7 @@ area *areaManager::findArea(area_id id) { bool areaManager::fault(void *fault_address, bool writeError) { // true = OK, false = panic. area *myArea; bool retVal; - error ("Faulting \n"); + //error ("Faulting \n"); // lock(); // Normally this should occur, but since we will be locked when we read/write anyway... myArea=findArea(fault_address); if (myArea) @@ -137,23 +137,23 @@ long areaManager::nextAreaID=0; // 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) { - error ("areaManager::createArea - Creating an area\n"); + //error ("areaManager::createArea - Creating an area\n"); lock(); 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); - error ("areaManager::createArea - setup complete\n"); + //error ("areaManager::createArea - setup complete\n"); 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"); atomic_add(&nextAreaID,1); newArea->setAreaID(nextAreaID); - error ("areaManager::createArea - new area's setAreaID called\n"); + //error ("areaManager::createArea - new area's setAreaID called\n"); addArea(newArea); - error ("areaManager::createArea - new area added to list\n"); + //error ("areaManager::createArea - new area added to list\n"); int retVal=newArea->getAreaID(); - error ("areaManager::createArea - new area id found\n"); + //error ("areaManager::createArea - new area id found\n"); unlock(); - error ("areaManager::createArea - Done Creating an area\n"); + //error ("areaManager::createArea - Done Creating an area\n"); return retVal; } @@ -166,11 +166,9 @@ area *findAreaGlobal(int areaID) { return NULL; } -// FIX: THIS IS WRONG! It will only clone areas in our areaManager. -// Should: find the specified area, create a new area to be its clone, and set it up int areaManager::cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType,pageState state,protectType protect) { int retVal; - error ("Cloning an area\n"); + //error ("Cloning an area\n"); lock(); area *oldArea=findArea(newAreaID); if (!oldArea) @@ -281,13 +279,15 @@ void areaManager::saver(void) { // mmap is basically map POSIX values to ours and call createAreaMappingFile... void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) { char name[MAXPATHLEN]; + if (fd<0) + return NULL; // Get the filename from fd... strcpy( name,"mmap - need to include fileName"); addressSpec addType=((flags&MAP_FIXED)?EXACT:ANY); protectType protType; - protType=(flags&PROT_WRITE)?writable:(flags&(PROT_READ|PROT_EXEC))?readable:none; + protType=(prot&PROT_WRITE)?writable:(prot&(PROT_READ|PROT_EXEC))?readable:none; //error ("flags = %x, anon = %x\n",flags,MAP_ANON); lock(); if (flags & MAP_ANON) { diff --git a/src/kernel/vm2/areaPool.C b/src/kernel/vm2/areaPool.C index 87184d773e..f24ea0d612 100644 --- a/src/kernel/vm2/areaPool.C +++ b/src/kernel/vm2/areaPool.C @@ -25,7 +25,7 @@ area *poolarea::get(void) else { page *newPage=vmBlock->pageMan->getPage(); - error ("poolarea::get: Getting new page %lx!\n",newPage->getAddress()); + //error ("poolarea::get: Getting new page %lx!\n",newPage->getAddress()); if (!newPage) throw ("Out of pages to allocate a pool!"); int newCount=PAGE_SIZE/sizeof(area); diff --git a/src/kernel/vm2/pageManager.C b/src/kernel/vm2/pageManager.C index de0be1be9c..96250d4ea5 100644 --- a/src/kernel/vm2/pageManager.C +++ b/src/kernel/vm2/pageManager.C @@ -62,12 +62,12 @@ void pageManager::freePage(page *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. acquire_sem(inUseLock); inUse.remove(toFree); - inUse.dump(); +// inUse.dump(); release_sem(inUseLock); acquire_sem(unusedLock); unused.add(toFree); - unused.dump(); +// unused.dump(); release_sem(unusedLock); } } diff --git a/src/kernel/vm2/vm.h b/src/kernel/vm2/vm.h index cd6a4ed72f..f3d56030db 100644 --- a/src/kernel/vm2/vm.h +++ b/src/kernel/vm2/vm.h @@ -16,6 +16,9 @@ struct vnode : public node { valid=false; } + + void dump(void) { error ("vnode::dump - fd = %d, offset = %ld, valid = %d\n",fd,offset,valid); + } }; #define B_OS_NAME_LENGTH 32 enum protectType {none=0,readable, writable,copyOnWrite}; diff --git a/src/kernel/vm2/vmInterface.C b/src/kernel/vm2/vmInterface.C index 02d822bfe0..4c67fa31fd 100644 --- a/src/kernel/vm2/vmInterface.C +++ b/src/kernel/vm2/vmInterface.C @@ -89,7 +89,7 @@ vmInterface::vmInterface(int pages) vmBlock->pageMan = new (currentAddress) pageManager; currentAddress=addToPointer(currentAddress,sizeof(pageManager)); vmBlock->pageMan->setup(addToPointer(vmBlock,PAGE_SIZE*pageCount),pages-pageCount); - error ("Set up Page Man\n"); + //error ("Set up Page Man\n"); vmBlock->areaPool = new (currentAddress) poolarea; currentAddress=addToPointer(currentAddress,sizeof(poolarea)); vmBlock->vpagePool = new (currentAddress) poolvpage; @@ -145,9 +145,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"); + //error ("vmInterface::createArea: Creating an area!\n"); retVal = getAM()->createArea(AreaName,pageCount,address,addType,state,protect); - error ("vmInterface::createArea: Done creating an area!\n"); + //error ("vmInterface::createArea: Done creating an area!\n"); return retVal; } @@ -159,9 +159,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"); + //error ("vmInterface::getAreaInfo: Getting info about an area!\n"); 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; } diff --git a/src/kernel/vm2/vnodeManager.C b/src/kernel/vm2/vnodeManager.C index d5936cc451..c8b20b3944 100644 --- a/src/kernel/vm2/vnodeManager.C +++ b/src/kernel/vm2/vnodeManager.C @@ -27,7 +27,7 @@ vpage *vnodeManager::findVnode(vnode &target) { // If this vnode is already in use, add this vpage to it and return one to clone. If not, add this vnode, with this vpage, and return null // This method will make a new vnode object -vpage *vnodeManager::addVnode(vnode &target,vpage &vp) { +vpage *vnodeManager::addVnode(vnode &target,vpage &vp, vnode **newOne) { vpage *retVal; error ("vnodeManager::addVnode : Adding by reference node %x, fd = %d, offset = %d\n",&target,target.fd,target.offset); vnode *found=reinterpret_cast(vnodes.find(&target)); @@ -35,12 +35,18 @@ vpage *vnodeManager::addVnode(vnode &target,vpage &vp) { found=new (vmBlock->vnodePool->get()) vnode; found->fd=target.fd; found->offset=target.offset; + found->valid=target.valid; vnodes.add(found); + *newOne=found; retVal=NULL; } - else + else { retVal=reinterpret_cast(found->vpages.top()); + *newOne=retVal->getBacking(); + } found->vpages.add(&vp); + error ("vnodeManager::addVnode returning %x, newOne = %x \n"); + return retVal; } @@ -71,5 +77,18 @@ bool vnodeManager::remove(vnode &target,vpage &vp) { throw ("An attempt to remove from an unknown vnode occured!\n"); } found->vpages.remove(&vp); - return (found->vpages.count()==0); + if (found->vpages.count()==0) { + vnodes.remove(found); + return true; + } + else + return false; +} + +void vnodeManager::dump(void) { + for (hashIterate hi(vnodes);node *cur=hi.get();) { + vnode *found=reinterpret_cast(cur); + error ("vnodeManager::dump found vnode:"); + found->dump(); + } } diff --git a/src/kernel/vm2/vnodeManager.h b/src/kernel/vm2/vnodeManager.h index 75ca5eb1a8..022a266a36 100644 --- a/src/kernel/vm2/vnodeManager.h +++ b/src/kernel/vm2/vnodeManager.h @@ -11,10 +11,10 @@ class vnodeManager public: vnodeManager(void); vpage *findVnode(vnode &target); // pass in a vnode, get back the "master" vpage - vpage *addVnode (vnode &target, vpage &vp); + vpage *addVnode (vnode &target, vpage &vp,vnode **retOne); vpage *addVnode(vnode *target,vpage &vp); bool remove(vnode &target,vpage &vp); - + void dump(void); private: hashTable vnodes; }; diff --git a/src/kernel/vm2/vnodePool.C b/src/kernel/vm2/vnodePool.C index 39786cbd83..e4cc19de74 100644 --- a/src/kernel/vm2/vnodePool.C +++ b/src/kernel/vm2/vnodePool.C @@ -22,7 +22,7 @@ vnode *poolvnode::get(void) else { page *newPage=vmBlock->pageMan->getPage(); - error ("poolvnode::get: Getting new page %lx!\n",newPage->getAddress()); + //error ("poolvnode::get: Getting new page %lx!\n",newPage->getAddress()); if (!newPage) throw ("Out of pages to allocate a pool!"); int newCount=PAGE_SIZE/sizeof(vnode); diff --git a/src/kernel/vm2/vpage.C b/src/kernel/vm2/vpage.C index 3c383dc99e..3b4dd721cf 100644 --- a/src/kernel/vm2/vpage.C +++ b/src/kernel/vm2/vpage.C @@ -11,12 +11,13 @@ extern vmHeaderBlock *vmBlock; // Write this vpage out if necessary void vpage::flush(void) { - if (protection==writable && dirty) { - //error (vpage::write_block: writing, backingNode->fd = %d, backingNode->offset = %d, address = %x\n",backingNode->fd, backingNode->offset,loc); + if (physPage && protection==writable && dirty) { + error ("vpage::write_block: writing, backingNode->fd = %d, backingNode->offset = %d, address = %x\n",backingNode->fd, backingNode->offset,physPage->getAddress()); 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)); + if (-1==write(backingNode->fd,(void *)(physPage->getAddress()),PAGE_SIZE)) + error ("vpage::flush: failed address =%x, fd = %d, offset = %d, errno = %d, %s\n", + start_address,backingNode->fd, backingNode->offset, 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); } @@ -24,12 +25,13 @@ void vpage::flush(void) { // Load this vpage in if necessary void vpage::refresh(void) { + error ("vpage::refresh: reading into %x\n",physPage->getAddress()); + backingNode->dump(); 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)) + if (-1==read(backingNode->fd,(void *)(physPage->getAddress()),PAGE_SIZE)) error ("vpage::refresh: failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno)); } @@ -57,11 +59,11 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType switch (share) { case CLONE: // This is a cloned area case SHARED: // This is a shared mmap - clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this); // Use the reference version which will make a new one if this one is not found + clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this,&backingNode); // Use the reference version which will make a new one if this one is not found if (clonedPage) physPage=clonedPage->physPage; break; case PRIVATE: // This is a one way share - we get others changes (until we make a change) but no one gets our changes - clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this); // Use the reference version which will make a new one if this one is not found + clonedPage=vmBlock->vnodeMan->addVnode(*backingNode,*this,&backingNode); // Use the reference version which will make a new one if this one is not found if (clonedPage) physPage=clonedPage->physPage; protection=(protection<=readable)?protection: copyOnWrite; break; @@ -84,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 (!physPage && (state!=LAZY) && (state!=NO_LOCK)) { 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. if (physPage) @@ -97,7 +99,7 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType // Destruction. void vpage::cleanup(void) { if (physPage) { // Note that free means release one reference - error ("vpage::cleanup, freeing physcal page %x\n",physPage); + //error ("vpage::cleanup, freeing physcal page %x\n",physPage); vmBlock->pageMan->freePage(physPage); // This does nothing if someone else is using the physical page } if (backingNode) { // If no one else is using this vnode, wipe it out @@ -119,6 +121,8 @@ void vpage::setProtection(protectType prot) { // true = OK, false = panic. 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")); + if (writeError && protection != copyOnWrite && protection != writable) + 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 dirty=true; if (protection==copyOnWrite) { // Else, this was just a "let me know when I am dirty"... @@ -144,11 +148,11 @@ bool vpage::fault(void *fault_address, bool writeError, int &in_count) { // 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=false; + dirty=writeError; // If the client is writing, we are now dirty (or will be when we get back to user land) in_count++; - error ("vpage::fault: Refreshed\n"); + //error ("vpage::fault: Refreshed\n"); dump(); - error ("vpage::fault: exiting\n"); + //error ("vpage::fault: exiting\n"); return true; } @@ -192,7 +196,7 @@ int vpage::getInt(unsigned long address,areaManager *manager) { if (!physPage) if (!manager->fault((void *)(address),false)) throw ("vpage::getInt"); - error ("vpage::getInt: About to return %d\n", *((char *)(address-start_address+physPage->getAddress()))); + //error ("vpage::getInt: About to return %d\n", *((char *)(address-start_address+physPage->getAddress()))); dump(); return *((int *)(address-start_address+physPage->getAddress())); } @@ -209,7 +213,7 @@ bool vpage::pager(int desperation) { //error ("vpage::pager start desperation = %d\n",desperation); if (!swappable) return false; - error ("vpage::pager swappable\n"); + //error ("vpage::pager swappable\n"); switch (desperation) { case 1: return false; break; case 2: if (!physPage || protection!=readable || locked) return false;break; @@ -218,11 +222,11 @@ bool vpage::pager(int desperation) { case 5: if (!physPage || locked) return false;break; default: return false;break; } - error ("vpage::pager flushing\n"); + //error ("vpage::pager flushing\n"); flush(); - error ("vpage::pager freeing\n"); + //error ("vpage::pager freeing\n"); vmBlock->pageMan->freePage(physPage); - error ("vpage::pager going to NULL\n"); + //error ("vpage::pager going to NULL\n"); physPage=NULL; return true; } diff --git a/src/kernel/vm2/vpage.h b/src/kernel/vm2/vpage.h index 26bf125d3e..1738d1c687 100644 --- a/src/kernel/vm2/vpage.h +++ b/src/kernel/vm2/vpage.h @@ -51,7 +51,9 @@ class vpage : public node // Debugging void dump(void) { - error ("Dumping vpage %p, address = %lx, physPage: \n",this,start_address); + error ("Dumping vpage %p, address = %lx, vnode-fd=%d, vnode-offset = %d, dirty = %d, swappable = %d, locked = %d\n", + this,start_address, ((backingNode)?(backingNode->fd):99999), ((backingNode)?(backingNode->offset):999999999), + dirty,swappable,locked); if (physPage) physPage->dump(); else diff --git a/src/kernel/vm2/vpagePool.C b/src/kernel/vm2/vpagePool.C index 6de305e5a2..246b52cee6 100644 --- a/src/kernel/vm2/vpagePool.C +++ b/src/kernel/vm2/vpagePool.C @@ -23,7 +23,7 @@ vpage *poolvpage::get(void) else { page *newPage=vmBlock->pageMan->getPage(); - error ("poolvpage::get: Getting new page %lx!\n",newPage->getAddress()); + //error ("poolvpage::get: Getting new page %lx!\n",newPage->getAddress()); if (!newPage) throw ("Out of pages to allocate a pool!"); int newCount=PAGE_SIZE/sizeof(vpage);