From 5fb6c38b6ee199522cde2fda1914e9c0ff417eea Mon Sep 17 00:00:00 2001 From: Michael Phipps Date: Sat, 14 Sep 2002 17:03:16 +0000 Subject: [PATCH] Another checkpoint. Big one, this time. Changed the whole way locking was done. What was I thinking? Many changes and cleanup ideas from Ingo (thanks!). Not perfect yet, but much better. Still a few things left to implement in the COW arena - mmap doesn't use it. Also need to finish the vpageManager which will cause mmap and cacheManager to use the same vnodes where possible. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1042 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/vm2/area.C | 76 ++++++------- src/kernel/vm2/areaManager.C | 187 +++++++++++++++++++++++++++---- src/kernel/vm2/areaManager.h | 94 +++++++++++++++- src/kernel/vm2/areaPool.C | 2 +- src/kernel/vm2/areaPool.h | 2 +- src/kernel/vm2/cacheManager.C | 12 ++ src/kernel/vm2/cacheManager.h | 3 +- src/kernel/vm2/list.h | 7 +- src/kernel/vm2/olTest.C | 102 +++++++++++++++++ src/kernel/vm2/olist.h | 69 ++++++++++++ src/kernel/vm2/page.h | 4 +- src/kernel/vm2/pageManager.C | 9 +- src/kernel/vm2/swapFileManager.C | 2 +- src/kernel/vm2/test.C | 51 +++++---- src/kernel/vm2/vm.h | 1 - src/kernel/vm2/vmInterface.C | 127 +++++++-------------- src/kernel/vm2/vmInterface.h | 3 +- src/kernel/vm2/vnodePool.C | 2 +- src/kernel/vm2/vnodePool.h | 2 +- src/kernel/vm2/vpage.C | 36 +++--- src/kernel/vm2/vpage.h | 11 +- src/kernel/vm2/vpageManager.h | 19 ++++ src/kernel/vm2/vpagePool.C | 2 +- src/kernel/vm2/vpagePool.h | 2 +- 24 files changed, 611 insertions(+), 214 deletions(-) create mode 100644 src/kernel/vm2/olTest.C create mode 100644 src/kernel/vm2/olist.h create mode 100644 src/kernel/vm2/vpageManager.h diff --git a/src/kernel/vm2/area.C b/src/kernel/vm2/area.C index 6602d142b3..c3d563954b 100644 --- a/src/kernel/vm2/area.C +++ b/src/kernel/vm2/area.C @@ -15,8 +15,9 @@ area::area(void) void area::setup (areaManager *myManager) { - printf ("area::setup setting up new area\n"); + //printf ("area::setup setting up new area\n"); manager=myManager; + //printf ("area::setup done setting up new area\n"); } unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount) @@ -28,7 +29,7 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque case EXACT: base=manager->getNextAddress(pageCount,requested); if (base!=requested) - return B_ERROR; + return 0; break; case BASE: base=manager->getNextAddress(pageCount,requested); @@ -40,6 +41,8 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque base=manager->getNextAddress(pageCount,KERNEL_BASE); break; case CLONE: base=0;break; // Not sure what to do... + default: // should never happen + throw ("Unknown type passed to mapAddressSpecToAddress"); } // printf ("area::mapAddressSpecToAddress, in type: %s, address = %x, size = %d\n", ((type==EXACT)?"Exact":(type==BASE)?"BASE":(type==ANY)?"ANY":(type==CLONE)?"CLONE":"ANY_KERNEL"), requested,pageCount); return base; @@ -51,8 +54,9 @@ status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works... vpage *newPage; - manager->lock(); unsigned long base=mapAddressSpecToAddress(type,requested,pageCount); + if (base==0) + return B_ERROR; for (int i=0;ivnodePool->get()) vnode; @@ -64,13 +68,13 @@ status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, vpages.add(newPage); // printf ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset); } - manager->unlock(); state=inState; start_address=base; - end_address=base+pageCount*PAGE_SIZE; + end_address=base+(pageCount*PAGE_SIZE)-1; *address=(void *)base; finalWrite=true; + return B_OK; } status_t area::createArea(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect) @@ -82,22 +86,23 @@ status_t area::createArea(char *inName, int pageCount,void **address, addressSpe finalWrite=false; unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works... - manager->lock(); - printf ("area::createArea: Locked in createArea\n"); +// printf ("area::createArea: Locked in createArea\n"); unsigned long base=mapAddressSpecToAddress(type,requested,pageCount); - printf ("area::createArea: base address = %d\n",base); + if (base==0) + return B_ERROR; +// printf ("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); } - manager->unlock(); start_address=base; - end_address=base+pageCount*PAGE_SIZE; + end_address=base+(pageCount*PAGE_SIZE)-1; *address=(void *)base; - printf ("area::createArea: unlocked in createArea\n"); +// printf ("area::createArea: unlocked in createArea\n"); + return B_OK; } status_t area::cloneArea(area *origArea, char *inName, void **address, addressSpec type,pageState inState,protectType protect) @@ -105,18 +110,14 @@ status_t area::cloneArea(area *origArea, char *inName, void **address, addressSp // printf ("area::cloneArea: entered\n"); strcpy(name,inName); int pageCount = origArea->getPageCount(); - manager->lock(); // printf ("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; // printf ("area::cloneArea: base address = %x\n",base); - if (origArea->getAreaManager()!=manager) // Else, already locked; - { - printf ("Holding dual locks! \n"); - origArea->getAreaManager()->lock(); - } for (struct node *cur=origArea->vpages.rock;cur;) { vpage *newPage,*page=(vpage *)cur; @@ -127,24 +128,21 @@ status_t area::cloneArea(area *origArea, char *inName, void **address, addressSp base+=PAGE_SIZE; cur=cur->next; } - if (origArea->getAreaManager()!=manager) // Else, already locked; - origArea->getAreaManager()->unlock(); state=inState; - end_address=base+pageCount*PAGE_SIZE; - manager->unlock(); + end_address=base+(pageCount*PAGE_SIZE)-1; *address=(void *)start_address; finalWrite=false; // printf ("area::cloneArea: unlocked\n"); + return B_OK; } void area::freeArea(void) { //printf ("area::freeArea: starting \n"); - manager->lock(); // vpages.dump(); node *cur; - while (cur=vpages.next()) + while ((cur=vpages.next())!=NULL) { //printf ("area::freeArea: wasting a page: %x\n",cur); vpage *page=reinterpret_cast(cur); @@ -156,16 +154,16 @@ void area::freeArea(void) vmBlock->vpagePool->put(page); } //printf ("area::freeArea: unlocking \n"); - manager->unlock(); //printf ("area::freeArea: ending \n"); } status_t area::getInfo(area_info *dest) { - // no need to lock here... + dest->area=areaID; strcpy(dest->name,name); dest->size=end_address-start_address; dest->lock=state; + dest->protection=protection; dest->team=manager->getTeam(); dest->ram_size=0; dest->in_count=0; @@ -190,7 +188,7 @@ bool area::contains(void *address) unsigned long base=(unsigned long)(address); // printf ("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) && (end_address>=base)); + return ((start_address<=base) && (base<=end_address)); } status_t area::resize(size_t newSize) @@ -200,7 +198,6 @@ status_t area::resize(size_t newSize) return B_OK; if (newSize>oldSize) { - manager->lock(); int pageCount = (newSize-oldSize) / PAGE_SIZE; vpage *newPage; for (int i=0;ilock(); int pageCount = (oldSize -newSize) / PAGE_SIZE; vpage *oldPage; struct node *cur; for (int i=0;inext;cur=cur->next); // INTENTIONAL - find the last one; - vpage *oldPage=(vpage *)cur; + oldPage=(vpage *)cur; + vpages.remove(cur); oldPage->cleanup(); vmBlock->vpagePool->put(oldPage); } } - manager->unlock(); + return B_OK; } status_t area::setProtection(protectType prot) { - manager->lock(); for (struct node *cur=vpages.rock;cur;cur=cur->next) { vpage *page=(vpage *)cur; page->setProtection(prot); } protection=prot; - manager->unlock(); + return B_OK; } vpage *area::findVPage(unsigned long address) @@ -246,6 +242,8 @@ vpage *area::findVPage(unsigned long address) for (struct node *cur=vpages.rock;cur;cur=cur->next) { vpage *page=(vpage *)cur; + //printf ("Examining following vpage, looking for address %lx\n",address); + //page->dump(); if (page->contains(address)) return page; } @@ -267,7 +265,7 @@ 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); + return page->getByte(address,manager); else return 0; } @@ -277,7 +275,7 @@ 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); + page->setByte(address,value,manager); } int area::getInt(unsigned long address) // This is for testing only @@ -285,7 +283,9 @@ int area::getInt(unsigned long address) // This is for testing only // No need to lock here... vpage *page=findVPage(address); if (page) - page->getInt(address); + return page->getInt(address,manager); + else + return 0; } void area::setInt(unsigned long address,int value) // This is for testing only @@ -293,7 +293,7 @@ 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); + page->setInt(address,value,manager); } void area::pager(int desperation) @@ -318,7 +318,7 @@ void area::saver(void) void area::dump(void) { - printf ("area::dump: size = %d, lock = %d, address = %x\n",end_address-start_address,state,start_address); + printf ("area::dump: size = %ld, lock = %d, address = %lx\n",end_address-start_address,state,start_address); for (struct node *cur=vpages.rock;cur;) { vpage *page=(vpage *)cur; diff --git a/src/kernel/vm2/areaManager.C b/src/kernel/vm2/areaManager.C index d7f6eff370..b3e6f57337 100644 --- a/src/kernel/vm2/areaManager.C +++ b/src/kernel/vm2/areaManager.C @@ -1,14 +1,26 @@ +#include +#include "mman.h" #include "areaManager.h" +#include "vmHeaderBlock.h" +#include "areaPool.h" +extern vmHeaderBlock *vmBlock; + +bool areaIsLessThan(void *a,void *b) +{ + return (((reinterpret_cast(a))->getStartAddress()) < (reinterpret_cast(b))->getStartAddress()); +} areaManager::areaManager(void) { team=0; // should be proc_get_current_proc_id() myLock=0; myLock=create_sem(1,"Area Manager Semaphore"); // Should have team name in it. + areas.setIsLessThan(areaIsLessThan); } unsigned long areaManager::getNextAddress(int pages, unsigned long start) { + // This function needs to deal with the possibility that we run out of address space... // areas.dump(); unsigned long end=start+(pages*PAGE_SIZE)-1; for (struct node *cur=areas.rock;cur;cur=cur->next) @@ -27,19 +39,54 @@ unsigned long areaManager::getNextAddress(int pages, unsigned long start) return start; } +void areaManager::freeArea(int areaID) +{ + printf ("areaManager::freeArea: begin\n"); + lock(); + area *oldArea=findArea(areaID); + //printf ("areaManager::freeArea: found area %x\n",oldArea); + if (oldArea) + { +// printf ("areaManager::freeArea: removing area %x from linked list\n",oldArea); +// printf ("areaManager::freeArea: areaManager = %x \n",manager); + removeArea(oldArea); +// printf ("areaManager::freeArea: deleting area %x \n",oldArea); + oldArea->freeArea(); +// printf ("areaManager::freeArea: freeArea complete \n"); + vmBlock->areaPool->put(oldArea); + } + else + printf ("areaManager::freeArea: unable to find requested area\n"); + unlock(); +} + +area *areaManager::findAreaLock(void *address) +{ + lock(); + area *retVal=findArea(address); + unlock(); + return retVal; +} + area *areaManager::findArea(char *address) { - for (struct node *cur=areas.rock;cur;cur=cur->next) + printf ("Finding area by string\n"); + lock(); + area *retVal=NULL; + for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next) { area *myArea=(area *)cur; if (myArea->nameMatch(address)) - return myArea; + retVal= myArea; } - return NULL; + unlock(); + return retVal; } area *areaManager::findArea(void *address) { + // THIS DOES NOT HAVE LOCKING - all callers must lock. + //printf ("Finding area by void * address\n"); for (struct node *cur=areas.rock;cur;cur=cur->next) { area *myArea=(area *)cur; @@ -52,73 +99,171 @@ area *areaManager::findArea(void *address) return NULL; } +area *areaManager::findAreaLock(area_id id) +{ + printf ("Finding area by areaID \n"); + lock(); + area *retVal=findArea(id); + unlock(); + return retVal; +} + area *areaManager::findArea(area_id id) { - for (struct node *cur=areas.rock;cur;cur=cur->next) + //printf ("Finding area by area_id\n"); + area *retVal=NULL; + for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next) { area *myArea=(area *)cur; if (myArea->getAreaID()==id) - return myArea; + retVal= myArea; } - return NULL; + return retVal; } bool areaManager::fault(void *fault_address, bool writeError) // true = OK, false = panic. { area *myArea; - if (myArea=findArea(fault_address)) - return myArea->fault(fault_address,writeError); + bool retVal; + printf ("Faulting \n"); + lock(); + myArea=findArea(fault_address); + if (myArea) + retVal= myArea->fault(fault_address,writeError); else - return false; + retVal= false; + unlock(); + return retVal; } +int areaManager::nextAreaID=0; + +int areaManager::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) +{ + printf ("Creating an area\n"); + lock(); + area *newArea = new (vmBlock->areaPool->get()) area; + // printf ("areaManager::createArea - got a new area (%p) from the areaPool\n",newArea); + newArea->setup(this); + // printf ("areaManager::createArea - setup complete\n"); + newArea->createArea(AreaName,pageCount,address,addType,state,protect); + // printf ("areaManager::createArea - new area's createArea called\n"); + newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE + // printf ("areaManager::createArea - new area's setAreaID called\n"); + addArea(newArea); + // printf ("areaManager::createArea - new area added to list\n"); + int retVal=newArea->getAreaID(); + // printf ("areaManager::createArea - new area id found\n"); + unlock(); + //printf ("Done Creating an area\n"); + return retVal; +} + +int areaManager::cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType,pageState state,protectType protect) + { + printf ("Cloning an area\n"); + lock(); + area *newArea = new (vmBlock->areaPool->get()) area; + newArea->setup(this); + area *oldArea=findArea(newAreaID); + newArea->cloneArea(oldArea,AreaName,address,addType,state,protect); + newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE + addArea(newArea); + int retVal=newArea->getAreaID(); + unlock(); + return retVal; + } + char areaManager::getByte(unsigned long address) { area *myArea; - if (myArea=findArea((void *)address)) - return myArea->getByte(address); + int retVal; + myArea=findArea((void *)address); + if (myArea) + retVal=myArea->getByte(address); else - return 0; + retVal= 0; + return retVal; } int areaManager::getInt(unsigned long address) { area *myArea; - if (myArea=findArea((void *)address)) - return myArea->getInt(address); + int retVal; + myArea=findArea((void *)address); + if (myArea) + retVal=myArea->getInt(address); else - return 0; + retVal= 0; + return retVal; } -void areaManager::setByte(unsigned long offset,char value) +void areaManager::setByte(unsigned long address,char value) { area *myArea; - if (myArea=findArea((void *)offset)) - myArea->setByte(offset,value); + myArea=findArea((void *)address); + if (myArea) + myArea->setByte(address,value); } -void areaManager::setInt(unsigned long offset,int value) +void areaManager::setInt(unsigned long address,int value) { area *myArea; - if (myArea=findArea((void *)offset)) - myArea->setInt(offset,value); + myArea=findArea((void *)address); + if (myArea) + myArea->setInt(address,value); } void areaManager::pager(int desperation) { + lock(); for (struct node *cur=areas.rock;cur;cur=cur->next) { area *myArea=(area *)cur; + //printf ("areaManager::pager; area = \n"); + //myArea->dump(); myArea->pager(desperation); } + unlock(); } void areaManager::saver(void) { + lock(); for (struct node *cur=areas.rock;cur;cur=cur->next) { area *myArea=(area *)cur; myArea->saver(); } + unlock(); } +void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) +{ + char name[MAXPATHLEN]; + // Get the filename from fd... + strcpy( name,"mmap - need to include fileName"); + + addressSpec addType=((flags&MAP_FIXED)?EXACT:ANY); + protectType protType=(prot&PROT_WRITE)?writable:(prot&PROT_READ)?readable:none; + // Not doing anything with MAP_SHARED and MAP_COPY - needs to be done + //printf ("flags = %x, anon = %x\n",flags,MAP_ANON); + lock(); + if (flags & MAP_ANON) + { + createArea(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr, addType ,LAZY,protType); + return addr; + } + + area *newArea = new (vmBlock->areaPool->get()) area; + newArea->setup(this); + //printf ("area = %x, start = %x\n",newArea, newArea->getStartAddress()); + newArea->createAreaMappingFile(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr,addType,LAZY,protType,fd,offset); + newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE + addArea(newArea); + newArea->getAreaID(); + //pageMan.dump(); + //newArea->dump(); + unlock(); + return addr; + } diff --git a/src/kernel/vm2/areaManager.h b/src/kernel/vm2/areaManager.h index c2d13f50f5..a8ff798a77 100644 --- a/src/kernel/vm2/areaManager.h +++ b/src/kernel/vm2/areaManager.h @@ -1,24 +1,112 @@ #include "area.h" +#include "olist.h" class areaManager // One of these per process { private: - list areas; + orderedList areas; team_id team; sem_id myLock; + static int nextAreaID; public: areaManager (); void addArea(area *newArea) {areas.add(newArea);} void removeArea(area *oldArea) {areas.remove(oldArea); } + void freeArea(int area); team_id getTeam(void) {return team;} unsigned long getNextAddress(int pages,unsigned long minimum=USER_BASE); area *findArea(void *address); + area *findAreaLock(void *address); area *findArea(char *address); area *findArea(area_id id); + area *findAreaLock(area_id id); + status_t setProtection(int areaID,protectType prot) + { + status_t retVal; + lock(); + area *myArea=findArea(areaID); + if (myArea) + retVal= myArea->setProtection(prot); + else + retVal= B_ERROR; + unlock(); + return retVal; + } + status_t resizeArea(int Area,size_t size) + { + status_t retVal; + lock(); + area *oldArea=findArea(Area); + if (oldArea) + retVal= oldArea->resize(size); + else + retVal= B_ERROR; + unlock(); + return retVal; + } + status_t getAreaInfo(int areaID,area_info *dest) + { + status_t retVal; + lock(); + area *oldArea=findArea(areaID); + if (oldArea) + retVal=oldArea->getInfo(dest); + else + retVal=B_ERROR; + unlock(); + return retVal; + } + status_t getInfoAfter(int32 & areaID,area_info *dest) + { + status_t retVal; + lock(); + area *oldArea=findArea(areaID); + if (oldArea->next) + { + area *newCurrent=(reinterpret_cast(oldArea->next)); + retVal=newCurrent->getInfo(dest); + areaID=(int)newCurrent; + } + else + retVal=B_ERROR; + unlock(); + return retVal; + } + int getAreaByName(char *name) + { + int retVal; + lock(); + area *oldArea=findArea(name); + if (oldArea) + retVal= oldArea->getAreaID(); + else + retVal= B_ERROR; + unlock(); + return retVal; + } + int createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) ; void pager(int desperation); void saver(void); - void lock() {acquire_sem(myLock);} - void unlock() {release_sem(myLock);} + void lock() + { + static long lockCount=0; + if (!((lockCount++)%200)) + printf ("locking\n"); + acquire_sem(myLock); + } + void unlock() {/*printf ("unlocking\n");*/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; + } + 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/areaPool.C b/src/kernel/vm2/areaPool.C index b3e63180ff..538e0220bb 100644 --- a/src/kernel/vm2/areaPool.C +++ b/src/kernel/vm2/areaPool.C @@ -31,7 +31,7 @@ area *poolarea::get(void) acquire_sem(inUse); //printf ("poolarea::get: Adding %d new elements to the pool!\n",newCount); for (int i=0;igetAddress()+(i*sizeof(area))))); + unused.add(((node *)(newPage->getAddress()+(i*sizeof(area))))); release_sem(inUse); return (get()); // A little cheat - call self again to get the first one from stack... } diff --git a/src/kernel/vm2/areaPool.h b/src/kernel/vm2/areaPool.h index aeb4bc3824..36c587cfae 100644 --- a/src/kernel/vm2/areaPool.h +++ b/src/kernel/vm2/areaPool.h @@ -15,7 +15,7 @@ class poolarea void put(area *in) { acquire_sem(inUse); - unused.add(in); + unused.add((node *)in); release_sem(inUse); } diff --git a/src/kernel/vm2/cacheManager.C b/src/kernel/vm2/cacheManager.C index e356425130..2ca2896387 100644 --- a/src/kernel/vm2/cacheManager.C +++ b/src/kernel/vm2/cacheManager.C @@ -3,6 +3,17 @@ #include #include "vmHeaderBlock.h" +bool cacheMemberIsLessThan(void *a,void *b) +{ + vnode *v1 = reinterpret_cast(a)->vn; + vnode *v2 = reinterpret_cast(b)->vn; + if (v1->fd < v2->fd) + return true; + if ((v1->fd==v2->fd) && (v1->offsetoffset)) + return true; + return false; +} + extern vmHeaderBlock *vmBlock; // TODO - we need to (somehow) make sure that the same vnodes here are shared with mmap. // Maybe a vnode manager... @@ -28,6 +39,7 @@ void *cacheManager::createBlock(vnode *target,bool readOnly) bool foundSpot=false; vpage *prev=NULL,*cur=NULL; unsigned long begin=CACHE_BEGIN; + // Find a place in the cache's virtual space to put this vnode... if (vpages.rock) for (cur=((vpage *)(vpages.rock));!foundSpot && cur;cur=(vpage *)(cur->next)) if (cur->getStartAddress()!=(void *)begin) diff --git a/src/kernel/vm2/cacheManager.h b/src/kernel/vm2/cacheManager.h index 244bd03793..3ba9652e60 100644 --- a/src/kernel/vm2/cacheManager.h +++ b/src/kernel/vm2/cacheManager.h @@ -2,6 +2,7 @@ #include #include #include +#include struct cacheMember : public node { @@ -12,7 +13,7 @@ struct cacheMember : public node class cacheManager : public area { private: - list cacheMembers; // Yes, this is slow and should be a hash table. This should be done prior to + orderedList cacheMembers; // Yes, this is slow and should be a hash table. This should be done prior to // moving into the kernel, so we can test it better. // While this very much mirrors the area's vpage list, it won't when it is a hash table... void *findBlock (vnode *target,bool readOnly); diff --git a/src/kernel/vm2/list.h b/src/kernel/vm2/list.h index 220880750a..3d3d9bf2f0 100644 --- a/src/kernel/vm2/list.h +++ b/src/kernel/vm2/list.h @@ -11,10 +11,9 @@ struct node class list { public: - list(void) {nodeCount=0;rock=NULL;} - void add (void *in) + list(void){nodeCount=0;rock=NULL;} + void add (node *newNode) { - struct node *newNode=reinterpret_cast(in); newNode->next=rock; rock=newNode; nodeCount++; @@ -60,7 +59,7 @@ class list { { for (struct node *cur=rock;cur;cur=cur->next) { - printf ("list::dump: At %x, next = %x\n",cur,cur->next); + printf ("list::dump: At %p, next = %p\n",cur,cur->next); } } struct node *rock; diff --git a/src/kernel/vm2/olTest.C b/src/kernel/vm2/olTest.C new file mode 100644 index 0000000000..fd346a8696 --- /dev/null +++ b/src/kernel/vm2/olTest.C @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include "olist.h" +#include "OS.h" + +struct iltTest : public node +{ + iltTest(int i) {value=i;} + int value; +}; + +bool ilt(void *a,void *b) +{ + iltTest *a1=reinterpret_cast(a); + iltTest *b1=reinterpret_cast(b); + if (a1->valuevalue) + return true; + return false; +} + +int main(int argc,char **argv) +{ + + // Test 1 - Try to add to foo without setting an isLessThan function + try { + orderedList foo; + node tmp; + foo.add(&tmp); + } + catch (const char *badness) + { + if (strcmp(badness,"Attempting to use an ordered list without setting up a 'toLessThan' function")) + printf ("Failure on adding with no isLessThan, error = %s\n", badness); + printf ("Success on adding with no isLessThan, \n" ); + } + catch(...) + { + printf ("Failure on adding with no isLessThan, unknown exception\n"); + } + + orderedList foo; + foo.setIsLessThan(ilt); + + printf ("Add the first couple, in order (easy)\n"); + iltTest first(1); + foo.add(&first); + iltTest second(2); + foo.add(&second); + foo.dump(); + + printf ("Add the next three, not in order (harder)\n"); + iltTest third(3); + iltTest fourth(4); + iltTest fifth(5); + foo.add(&fourth); + foo.add(&third); + foo.add(&fifth); + foo.dump(); + while (iltTest *n=(iltTest *)(foo.next())) + printf ("Popped %d\n",n->value); + + orderedList bar; + bar.setIsLessThan(ilt); + while (iltTest *n=(iltTest *)(bar.next())) + printf ("Popped %d\n",n->value); + for (int a=0;a<100;a++) + bar.add(new iltTest(a)); + while (iltTest *n=(iltTest *)(bar.next())) + printf ("Popped %d\n",n->value); + for (int a=1000;a>=0;a--) + bar.add(new iltTest(a)); + while (iltTest *n=(iltTest *)(bar.next())) + if (!(n->value%50)) printf ("Popped %d\n",n->value); + + printf ("Setting up simple case\n"); + foo.add(&first); + foo.dump(); + printf ("Removing simple case\n"); + foo.remove(&first); + foo.dump(); + + printf ("Setting up middle case\n"); + foo.add(&first); + foo.add(&second); + foo.dump(); + printf ("Removing middle case\n"); + foo.remove(&second); + foo.dump(); + foo.remove(&first); + + printf ("Setting up final case\n"); + foo.add(&first); + foo.add(&second); + foo.add(&third); + foo.dump(); + printf ("Removing final case\n"); + foo.remove(&second); + foo.dump(); + return 0; +} diff --git a/src/kernel/vm2/olist.h b/src/kernel/vm2/olist.h new file mode 100644 index 0000000000..a2bda57512 --- /dev/null +++ b/src/kernel/vm2/olist.h @@ -0,0 +1,69 @@ +#ifndef _OLIST_H +#define _OLIST_H +#include "list.h" + +static bool throwException (void *foo, void *bar) +{ + throw ("Attempting to use an ordered list without setting up a 'toLessThan' function"); +} + +class orderedList : public list +{ + public: + orderedList(void) {nodeCount=0;rock=NULL; isLessThan=throwException; } + + void setIsLessThan (bool (*iLT)(void *,void *)) { isLessThan=iLT; } + + void add(node *in) + { + nodeCount++; + //printf ("orderedList::add starting\n"); + if (!rock || isLessThan(in,rock)) + { // special case - this will be the first one + //printf ("orderedList::specialCase starting\n"); + in->next=rock; + rock=in; + } + else + { + //printf ("orderedList::Normal Case starting\n"); + bool done=false; + for (struct node *cur=rock;cur && !done;cur=cur->next) + if (!(cur->next) || isLessThan(in,cur->next)) + { // If we have found our niche, *OR* this is the last element, insert here. + //printf ("orderedList::Normal Case Adding Start\n"); + in->next=cur->next; + cur->next=in; + done=true; + //printf ("orderedList::Normal Case Adding END\n"); + } + //printf ("orderedList::Normal Case ending\n"); + } + } + + void remove(node *toNuke) + { + if (rock==toNuke) + { + rock=rock->next; + nodeCount--; + } + else + { + bool done=false; + for (struct node *cur=rock;!done && (cur->next);cur=cur->next) + if (cur->next==toNuke) + { + cur->next=toNuke->next; + nodeCount--; + done=true; + } + else if (isLessThan(cur->next,toNuke)) // this is backwards intentionally + done=true; + } + } + + private: + bool (*isLessThan)(void *a,void *b); +}; +#endif diff --git a/src/kernel/vm2/page.h b/src/kernel/vm2/page.h index 8d655bf35d..8fe87fb348 100644 --- a/src/kernel/vm2/page.h +++ b/src/kernel/vm2/page.h @@ -7,11 +7,11 @@ class page : public node { void *cpuSpecific; void *physicalAddress; public: - int count; + long count; // Yes, this is large. However, the only atomic add that I have in userland works on int32's. In kernel land, we could shrink this page(void) {cpuSpecific=NULL;physicalAddress=NULL;}; void setup (void *address) {count=0;physicalAddress=address;}; void zero(void); unsigned long getAddress(void) {return (unsigned long)physicalAddress;} - void dump(void) { printf ("Page %x, physicalAddress = %x\n",this,getAddress()); } + void dump(void) { printf ("Page %p, physicalAddress = %lx\n",this,getAddress()); } }; #endif diff --git a/src/kernel/vm2/pageManager.C b/src/kernel/vm2/pageManager.C index a7866a8407..7af4de61d4 100644 --- a/src/kernel/vm2/pageManager.C +++ b/src/kernel/vm2/pageManager.C @@ -22,7 +22,7 @@ void pageManager::setup(void *area,int pages) //printf ("newPage = %x, setup = %x\n",newPage,addOffset(area,(i+pageOverhead)*PAGE_SIZE)); //printf ("i = %d, sizeof(page) = %x, pageOverhead = %d\n",i,sizeof(page),pageOverhead); //newPage->dump(); - unused.add(addOffset(area,i*sizeof(page))); + unused.add(newPage); } cleanLock=create_sem (1,"clean_lock"); @@ -77,9 +77,7 @@ page *pageManager::getPage(void) void pageManager::freePage(page *toFree) { // printf ("Inside freePage; old value = %d",toFree->count); - toFree->count--; -// printf (" new value = %d, page = %x\n",toFree->count,toFree->getAddress()); - if (toFree->count==0) + if (atomic_add(&(toFree->count),-1)==0) { acquire_sem(inUseLock); inUse.remove(toFree); @@ -88,6 +86,7 @@ void pageManager::freePage(page *toFree) unused.add(toFree); release_sem(unusedLock); } +// printf (" new value = %d, page = %x\n",toFree->count,toFree->getAddress()); } void pageManager::cleaner(void) @@ -99,11 +98,11 @@ void pageManager::cleaner(void) //printf ("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); - release_sem(unusedLock); //printf ("pageManager::cleaner: All done with vacuum a page\n"); snooze(125000); } diff --git a/src/kernel/vm2/swapFileManager.C b/src/kernel/vm2/swapFileManager.C index ff155ba8f6..82e6f2a014 100644 --- a/src/kernel/vm2/swapFileManager.C +++ b/src/kernel/vm2/swapFileManager.C @@ -29,10 +29,10 @@ void swapFileManager::write_block(vnode &node,void *loc,unsigned long size) void swapFileManager::read_block(vnode &node,void *loc,unsigned long size) { - lseek(node.fd,node.offset,SEEK_SET); if (node.valid==false) return; // Do nothing. This prevents "garbage" data on disk from being read in... //printf ("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); } diff --git a/src/kernel/vm2/test.C b/src/kernel/vm2/test.C index 04bc34f962..51cba16efd 100644 --- a/src/kernel/vm2/test.C +++ b/src/kernel/vm2/test.C @@ -11,27 +11,36 @@ void writeByte(unsigned long addr,unsigned int offset, char value) { vm.setByte( unsigned char readByte(unsigned long addr,unsigned int offset ) { char value=vm.getByte(addr+offset); return value; } -int createFillAndTest(int pages) +int createFillAndTest(int pages,char *name) { try{ unsigned long addr; int area1; - printf ("createFillAndTest: about to create \n"); + printf ("%s: createFillAndTest: about to create \n",name); area1=vm.createArea("Mine",pages,(void **)(&addr)); - printf ("createFillAndTest: create done\n"); + printf ("%s: createFillAndTest: create done\n",name); for (int i=0;iinitialSnooze); printf ("Creating %s area\n",params->name); - area1=createFillAndTest(params->areaSize); + area1=createFillAndTest(params->areaSize,params->name); snooze(params->holdSnooze); printf ("Freeing %s area\n",params->name); vm.freeArea(area1); @@ -71,20 +80,20 @@ int32 getInfoTest(void *parameters) { snooze(params->initialSnooze); //printf ("Creating %s area\n",params->name); - area1=createFillAndTest(params->areaSize); + area1=createFillAndTest(params->areaSize,params->name); snooze(params->holdSnooze); vm.getAreaInfo(area1,&ai); printf ("Area info : \n"); printf ("name : %s\n",ai.name); - printf ("size : %d\n",ai.size); - printf ("lock : %d\n",ai.lock); - printf ("team : %d\n",ai.team); - printf ("ram_size : %d\n",ai.ram_size); - printf ("in_count : %d\n",ai.in_count); - printf ("out_count : %d\n",ai.out_count); - printf ("copy_count : %d\n",ai.copy_count); - printf ("address : %x\n",ai.address); + printf ("size : %ld\n",ai.size); + printf ("lock : %ld\n",ai.lock); + printf ("team : %ld\n",ai.team); + printf ("ram_size : %ld\n",ai.ram_size); + printf ("in_count : %ld\n",ai.in_count); + printf ("out_count : %ld\n",ai.out_count); + printf ("copy_count : %ld\n",ai.copy_count); + printf ("address : %p\n",ai.address); printf ("Freeing %s area\n",params->name); vm.freeArea(area1); @@ -105,7 +114,7 @@ int32 mmapTest (void *parameters) printf ("Creating %s mmap\n",params->name); snooze(params->holdSnooze); map=vm.mmap(NULL,size,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0); - printf ("mmap address = %x\n",map); + printf ("mmap address = %p\n",map); for (int i=0;iinitialSnooze); // printf ("Creating %s area, size = %d\n",params->name,params->areaSize); - area1=createFillAndTest(params->areaSize); + area1=createFillAndTest(params->areaSize,params->name); // printf ("cloning, create done \n"); area2=vm.cloneArea(area1,"Clone1",&cloneAddr); for (int i=0;iareaSize*PAGE_SIZE;i++) if (i%256!=readByte((int32)cloneAddr,i)) - printf ("ERROR! Clone Byte at offset %d of %x does not match: expected: %d, found: %d\n",i,cloneAddr,i%256,readByte((int32)cloneAddr,i)); + printf ("ERROR! Clone Byte at offset %d of %p does not match: expected: %d, found: %d\n",i,cloneAddr,i%256,readByte((int32)cloneAddr,i)); // printf ("Snoozing, compare done \n"); snooze(params->holdSnooze); // printf ("Freeing %s area\n",params->name); @@ -157,9 +166,9 @@ int main(int argc,char **argv) resume_thread(spawn_thread(loopTest,"area test 1",0,&area1Params)); resume_thread(spawn_thread(loopTest,"area test 2",0,&area2Params)); resume_thread(spawn_thread(loopTest,"area test 3",0,&area3Params)); - resume_thread(spawn_thread(getInfoTest,"info test 1",0,&info1Params)); - resume_thread(spawn_thread(mmapTest,"mmap test 1",0,&mmap1Params)); - resume_thread(spawn_thread(cloneTest,"clone test 1",0,&clone1Params)); + //resume_thread(spawn_thread(getInfoTest,"info test 1",0,&info1Params)); + //resume_thread(spawn_thread(mmapTest,"mmap test 1",0,&mmap1Params)); + //resume_thread(spawn_thread(cloneTest,"clone test 1",0,&clone1Params)); snooze(1000000000); diff --git a/src/kernel/vm2/vm.h b/src/kernel/vm2/vm.h index c3b88fda6c..8c8554e477 100644 --- a/src/kernel/vm2/vm.h +++ b/src/kernel/vm2/vm.h @@ -16,7 +16,6 @@ struct vnode : public node count=0; } }; -typedef unsigned long owningProcess; #define B_OS_NAME_LENGTH 32 enum protectType {none=0,readable, writable,copyOnWrite,symCopyOnWrite}; enum pageState {FULL,CONTIGUOUS,LAZY,NO_LOCK,LOMEM}; diff --git a/src/kernel/vm2/vmInterface.C b/src/kernel/vm2/vmInterface.C index a1866872db..586013ee59 100644 --- a/src/kernel/vm2/vmInterface.C +++ b/src/kernel/vm2/vmInterface.C @@ -14,6 +14,8 @@ vmHeaderBlock *vmBlock; static areaManager am; +// The purpose of this interface is to validate options, translate where necessary and pass through to the areaManager. + areaManager *getAM(void) { return &am; @@ -62,7 +64,7 @@ int32 pagerThread(void *areaMan) vmInterface::vmInterface(int pages) { char temp[1000]; - sprintf (temp,"vm_test_clone_%d",getpid()); + sprintf (temp,"vm_test_clone_%ld",getpid()); if (clone_area(temp,(void **)(&vmBlock),B_ANY_ADDRESS,B_WRITE_AREA,find_area("vm_test"))<0) { // This is compatability for in BeOS usage only... @@ -97,7 +99,6 @@ vmInterface::vmInterface(int pages) //printf ("vmBlock is at %x, end of structures is at %x, pageMan called with address %x, pages = %d\n",vmBlock,currentAddress,addToPointer(vmBlock,PAGE_SIZE*pageCount),pages-pageCount); vmBlock->pageMan->setup(addToPointer(vmBlock,PAGE_SIZE*pageCount),pages-pageCount); } - nextAreaID=0; resume_thread(spawn_thread(cleanerThread,"cleanerThread",0,(vmBlock->pageMan))); resume_thread(spawn_thread(saverThread,"saverThread",0,getAM())); @@ -106,98 +107,68 @@ vmInterface::vmInterface(int pages) int vmInterface::getAreaByAddress(void *address) { - area *myArea = getAM()->findArea(address); + int retVal; + area *myArea = getAM()->findAreaLock(address); if (myArea) - return myArea->getAreaID(); + retVal= myArea->getAreaID(); else - return B_ERROR; + retVal= B_ERROR; + return retVal; } status_t vmInterface::setAreaProtection(int Area,protectType prot) { - area *myArea = getAM()->findArea(Area); - if (myArea) - return myArea->setProtection(prot); - else - return B_ERROR; + status_t retVal; + retVal= getAM()->setProtection(Area,prot); + return retVal; } status_t vmInterface::resizeArea(int Area,size_t size) { - area *oldArea; - oldArea=getAM()->findArea(Area); - if (oldArea) - return oldArea->resize(size); - else - return B_ERROR; + status_t retVal; + retVal = getAM()->resizeArea(Area,size); + return retVal; } int vmInterface::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) { - area *newArea = new (vmBlock->areaPool->get()) area; - areaManager *foo; - printf ("vmInterface::createArea - got a new area (%x) from the areaPool\n",newArea); - foo=getAM(); - newArea->setup(getAM()); - newArea->createArea(AreaName,pageCount,address,addType,state,protect); - newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE - getAM()->addArea(newArea); - return newArea->getAreaID(); + int retVal; + retVal = getAM()->createArea(AreaName,pageCount,address,addType,state,protect); + return retVal; } -void vmInterface::freeArea(int Area) +void vmInterface::freeArea(int area) { - //printf ("vmInterface::freeArea: begin\n"); - area *oldArea=getAM()->findArea(Area); - //printf ("vmInterface::freeArea: found area %x\n",oldArea); - if (oldArea) - { -// printf ("vmInterface::freeArea: removing area %x from linked list\n",oldArea); - areaManager *manager=getAM(); -// printf ("vmInterface::freeArea: areaManager = %x \n",manager); - manager->removeArea(oldArea); -// printf ("vmInterface::freeArea: deleting area %x \n",oldArea); - oldArea->freeArea(); -// printf ("vmInterface::freeArea: freeArea complete \n"); - vmBlock->areaPool->put(oldArea); - } - else - printf ("vmInterface::freeArea: unable to find requested area\n"); + getAM()->freeArea(area); } status_t vmInterface::getAreaInfo(int Area,area_info *dest) { - area *oldArea=getAM()->findArea(Area); - if (oldArea) - return oldArea->getInfo(dest); - else - printf ("vmInterface::getAreaInfo: unable to find requested area\n"); + status_t retVal; + retVal = getAM()->getAreaInfo(Area,dest); + return retVal; } status_t vmInterface::getNextAreaInfo(int process,int32 *cookie,area_info *dest) { - area *oldArea=getAM()->findArea(*cookie); - area *newArea=(area *)(oldArea->next); - if (newArea) - return newArea->getInfo(dest); - else - return B_BAD_VALUE; + status_t retVal; + // We *SHOULD* be getting the AM for this process. Something for HW integration time... + retVal = getAM()->getInfoAfter(*cookie,dest); + return retVal; } int vmInterface::getAreaByName(char *name) { - return getAM()->findArea(name)->getAreaID(); + int retVal; + retVal = getAM()->getAreaByName(name); + return retVal; } int vmInterface::cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType=ANY, pageState state=NO_LOCK, protectType prot=writable) { - area *newArea = new (vmBlock->areaPool->get()) area; - newArea->setup(getAM()); - area *oldArea=getAM()->findArea(newAreaID); - newArea->cloneArea(oldArea,AreaName,address,addType,state,prot); - newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE - getAM()->addArea(newArea); - return newArea->getAreaID(); + int retVal; + retVal = getAM()->cloneArea(newAreaID,AreaName,address, addType, state, prot); + return retVal; } void vmInterface::pager(void) @@ -228,36 +199,14 @@ void vmInterface::cleaner(void) void *vmInterface::mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) { - char name[MAXPATHLEN]; - // Get the filename from fd... - strcpy( name,"mmap - need to include fileName"); - - addressSpec addType=((flags&MAP_FIXED)?EXACT:ANY); - protectType protType=(prot&PROT_WRITE)?writable:(prot&PROT_READ)?readable:none; - // Not doing anything with MAP_SHARED and MAP_COPY - needs to be done - //printf ("flags = %x, anon = %x\n",flags,MAP_ANON); - if (flags & MAP_ANON) - { - createArea(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr, addType ,LAZY,protType); - return addr; - } - - area *newArea = new (vmBlock->areaPool->get()) area; - newArea->setup(getAM()); - //printf ("area = %x, start = %x\n",newArea, newArea->getStartAddress()); - newArea->createAreaMappingFile(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr,addType,LAZY,protType,fd,offset); - newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE - getAM()->addArea(newArea); - newArea->getAreaID(); - //pageMan.dump(); - //newArea->dump(); - return addr; + void *retVal; + retVal = getAM()->mmap(addr,len,prot,flags,fd,offset); + return retVal; } status_t vmInterface::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... - int area=getAreaByAddress(addr); - freeArea(area); - //pageMan.dump(); + int retVal; + retVal = getAM()->munmap(addr,len); + return retVal; } diff --git a/src/kernel/vm2/vmInterface.h b/src/kernel/vm2/vmInterface.h index b18488e7b0..f2c6511171 100644 --- a/src/kernel/vm2/vmInterface.h +++ b/src/kernel/vm2/vmInterface.h @@ -5,7 +5,6 @@ class vmInterface // This is the class that "owns" all of the managers. { private: - int nextAreaID; areaManager *getAM(void); // This is for testing only... public: vmInterface(int pages); @@ -28,6 +27,8 @@ class vmInterface // This is the class that "owns" all of the managers. void pager(void); void saver(void); void cleaner(void); + status_t writeCachedBlock(int fd, size_t offset, void *data); + status_t readCachedBlock(int fd, size_t offset, void *data); 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 int getInt(unsigned long offset) {return getAM()->getInt(offset);} // This is for testing only diff --git a/src/kernel/vm2/vnodePool.C b/src/kernel/vm2/vnodePool.C index c65a317070..c9d3bf679c 100644 --- a/src/kernel/vm2/vnodePool.C +++ b/src/kernel/vm2/vnodePool.C @@ -29,7 +29,7 @@ vnode *poolvnode::get(void) acquire_sem(inUse); //printf ("poolvnode::get: Adding %d new elements to the pool!\n",newCount); for (int i=0;igetAddress()+(i*sizeof(vnode))))); + unused.add(((node *)(newPage->getAddress()+(i*sizeof(vnode))))); release_sem(inUse); return (get()); // A little cheat - call self again to get the first one from stack... } diff --git a/src/kernel/vm2/vnodePool.h b/src/kernel/vm2/vnodePool.h index 6ad7d73b86..f7e68a3248 100644 --- a/src/kernel/vm2/vnodePool.h +++ b/src/kernel/vm2/vnodePool.h @@ -16,7 +16,7 @@ class poolvnode void put(vnode *in) { acquire_sem(inUse); - unused.add(in); + unused.add((node *)in); release_sem(inUse); } diff --git a/src/kernel/vm2/vpage.C b/src/kernel/vm2/vpage.C index c676395cea..21b4cf5c50 100644 --- a/src/kernel/vm2/vpage.C +++ b/src/kernel/vm2/vpage.C @@ -1,6 +1,7 @@ #include "vpage.h" #include "vnodePool.h" #include "vmHeaderBlock.h" +#include "areaManager.h" extern vmHeaderBlock *vmBlock; @@ -33,7 +34,6 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType end_address=start+PAGE_SIZE-1; protection=prot; swappable=(state==NO_LOCK); - dirty=true; if (backing) { @@ -50,6 +50,7 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType physMem->count++; physPage=physMem; } + dirty=(physPage!=NULL); //printf ("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)); } @@ -73,7 +74,7 @@ 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 -// printf ("vpage::fault: virtual address = %x, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false")); + printf ("vpage::fault: virtual address = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false")); if (writeError) { dirty=true; @@ -107,39 +108,42 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa return true; } -char vpage::getByte(unsigned long address) +char vpage::getByte(unsigned long address,areaManager *manager) { -// printf ("vpage::getByte: address = %d\n",address ); + //printf ("vpage::getByte: address = %ld\n",address ); if (!physPage) - if (!fault((void *)(address),false)) - throw ("vpage::getByte",address,0); -// printf ("vpage::getByte: About to return %d\n", *((char *)(address-start_address+physPage->getAddress()))); + if (!manager->fault((void *)(address),false)) + throw ("vpage::getByte"); + //printf ("vpage::getByte: About to return %d\n", *((char *)(address-start_address+physPage->getAddress()))); return *((char *)(address-start_address+physPage->getAddress())); } -void vpage::setByte(unsigned long address,char value) +void vpage::setByte(unsigned long address,char value,areaManager *manager) { // printf ("vpage::setByte: address = %d, value = %d\n",address, value); if (!physPage) - if (!fault((void *)(address),true)) - throw ("vpage::setByte",address,(int)value); + if (!manager->fault((void *)(address),true)) + throw ("vpage::setByte"); *((char *)(address-start_address+physPage->getAddress()))=value; // printf ("vpage::setByte: physical address = %d, value = %d\n",physPage->getAddress(), *((char *)(physPage->getAddress()))); } -int vpage::getInt(unsigned long address) +int vpage::getInt(unsigned long address,areaManager *manager) { + printf ("vpage::getInt: address = %ld\n",address ); if (!physPage) - if (!fault((void *)(address),false)) - throw ("vpage::getInt",address,0); + if (!manager->fault((void *)(address),false)) + throw ("vpage::getInt"); + printf ("vpage::getInt: About to return %d\n", *((char *)(address-start_address+physPage->getAddress()))); + dump(); return *((int *)(address-start_address+physPage->getAddress())); } -void vpage::setInt(unsigned long address,int value) +void vpage::setInt(unsigned long address,int value,areaManager *manager) { if (!physPage) - if (!fault((void *)(address),true)) - throw ("vpage::setInt",address,value); + if (!manager->fault((void *)(address),true)) + throw ("vpage::setInt"); *((int *)(address-start_address+physPage->getAddress()))=value; } diff --git a/src/kernel/vm2/vpage.h b/src/kernel/vm2/vpage.h index 3cdda93b7d..9dfc9081d2 100644 --- a/src/kernel/vm2/vpage.h +++ b/src/kernel/vm2/vpage.h @@ -4,6 +4,7 @@ #include #include +class areaManager; class vpage : public node { private: @@ -35,15 +36,15 @@ class vpage : public node void dump(void) { - printf ("Dumping vpage %x, address = %x, \n\t physPage: ",this,start_address); + printf ("Dumping vpage %p, address = %lx, \n\t physPage: ",this,start_address); if (physPage) physPage->dump(); else printf ("NULL\n"); } - char getByte(unsigned long offset); // This is for testing only - void setByte(unsigned long offset,char value); // This is for testing only - int getInt(unsigned long offset); // This is for testing only - void setInt(unsigned long offset,int value); // This is for testing only + char getByte(unsigned long offset,areaManager *manager); // This is for testing only + void setByte(unsigned long offset,char value,areaManager *manager); // This is for testing only + int getInt(unsigned long offset,areaManager *manager); // This is for testing only + void setInt(unsigned long offset,int value,areaManager *manager); // This is for testing only }; #endif diff --git a/src/kernel/vm2/vpageManager.h b/src/kernel/vm2/vpageManager.h new file mode 100644 index 0000000000..faee29782b --- /dev/null +++ b/src/kernel/vm2/vpageManager.h @@ -0,0 +1,19 @@ +// This manager holds all of the vpages. +// It creates them from the vpage pool +// and ensures that no two vpages point to +// the same vnode without also pointing to +// the same physical memory. Thus, cached disk +// blocks and mmapped memory always stay in sync. +// mmap seems to not want this to happen for a +// couple of cases - MAP_PRIVATE and MAP_COPY. +// If we decided to ever build these, we would +// have to make some changes. + +class vpageManager +{ + private: + + public: + vpage *getVpage(vnode &vn); + void putVpage(vpage &vp); +} diff --git a/src/kernel/vm2/vpagePool.C b/src/kernel/vm2/vpagePool.C index ea126c7e1e..fb9d842708 100644 --- a/src/kernel/vm2/vpagePool.C +++ b/src/kernel/vm2/vpagePool.C @@ -30,7 +30,7 @@ vpage *poolvpage::get(void) acquire_sem(inUse); //printf ("poolvpage::get: Adding %d new elements to the pool!\n",newCount); for (int i=0;igetAddress()+(i*sizeof(vpage))))); + unused.add(((node *)(newPage->getAddress()+(i*sizeof(vpage))))); release_sem(inUse); return (get()); // A little cheat - call self again to get the first one from stack... } diff --git a/src/kernel/vm2/vpagePool.h b/src/kernel/vm2/vpagePool.h index 9e7bed176a..6d3a5c9a1b 100644 --- a/src/kernel/vm2/vpagePool.h +++ b/src/kernel/vm2/vpagePool.h @@ -15,7 +15,7 @@ class poolvpage void put(vpage *in) { acquire_sem(inUse); - unused.add(in); + unused.add((node *)in); release_sem(inUse); }