diff --git a/src/kernel/vm2/area.C b/src/kernel/vm2/area.C index 14a7550755..5003c3b658 100644 --- a/src/kernel/vm2/area.C +++ b/src/kernel/vm2/area.C @@ -29,9 +29,7 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque break; case CLONE: base=0;break; // Not sure what to do... } - 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); +// 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; } @@ -48,9 +46,10 @@ status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, vnode *newVnode=new vnode; newVnode->fd=fd; newVnode->offset=offset+PAGE_SIZE*i; + newVnode->valid=true; newPage = new vpage(base+PAGE_SIZE*i,newVnode,NULL,protect,inState); vpages.add(newPage); - printf ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset); +// printf ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset); } manager->unlock(); @@ -58,31 +57,71 @@ status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, start_address=base; end_address=base+pageCount*PAGE_SIZE; *address=(void *)base; + finalWrite=true; } 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... + manager->lock(); //printf ("area::createArea: Locked in createArea\n"); - unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works... unsigned long base=mapAddressSpecToAddress(type,requested,pageCount); //printf ("area::createArea: base address = %d\n",base); - vpage *newPage; for (int i=0;iunlock(); start_address=base; end_address=base+pageCount*PAGE_SIZE; - manager->unlock(); *address=(void *)base; //printf ("area::createArea: unlocked in createArea\n"); } +status_t area::cloneArea(area *origArea, char *inName, void **address, addressSpec type,pageState inState,protectType protect) + { +// 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); + 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; + // Cloned area has the same physical page and backing store... + newPage = new vpage(base,page->getBacking(),page->getPhysPage(),protect,inState); + vpages.add(newPage); + 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(); + *address=(void *)start_address; + finalWrite=false; +// printf ("area::cloneArea: unlocked\n"); + } + void area::freeArea(void) { //printf ("area::freeArea: starting \n"); @@ -93,7 +132,8 @@ void area::freeArea(void) { //printf ("area::freeArea: wasting a page: %x\n",cur); vpage *page=(vpage *)cur; - page->flush(); + if (finalWrite) + page->flush(); //printf ("area::freeArea: flushed a page \n"); cur=cur->next; delete page; // Probably need to add a destructor @@ -257,3 +297,14 @@ 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); + for (struct node *cur=vpages.rock;cur;) + { + vpage *page=(vpage *)cur; + page->dump(); + cur=cur->next; + } + } + diff --git a/src/kernel/vm2/area.h b/src/kernel/vm2/area.h index ed39e627d6..3e47d94dc0 100644 --- a/src/kernel/vm2/area.h +++ b/src/kernel/vm2/area.h @@ -14,6 +14,7 @@ class area : public node char name[B_OS_NAME_LENGTH]; pageState state; protectType protection; + bool finalWrite; int areaID; int in_count; int out_count; @@ -28,6 +29,7 @@ class area : public node unsigned long mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount); 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); int getAreaID(void) {return areaID;} void setAreaID(int id) {areaID=id;} void freeArea(void); @@ -40,7 +42,11 @@ class area : public node unsigned long getStartAddress(void) {return start_address;} void pager(int desperation); void saver(void); + unsigned long getSize(void) {return getEndAddress()-getStartAddress();} + unsigned long getPageCount(void) {return (getEndAddress()-getStartAddress())/PAGE_SIZE;} + areaManager *getAreaManager(void) {return manager;} + void dump(void); bool fault(void *fault_address, bool writeError); // true = OK, false = panic. char getByte(unsigned long ); // This is for testing only diff --git a/src/kernel/vm2/areaManager.C b/src/kernel/vm2/areaManager.C index d1993e87a6..a92918b553 100644 --- a/src/kernel/vm2/areaManager.C +++ b/src/kernel/vm2/areaManager.C @@ -43,6 +43,7 @@ area *areaManager::findArea(void *address) { area *myArea=(area *)cur; // printf ("areaManager::findArea: Looking for %x between %x and %x\n",address,myArea->getStartAddress(),myArea->getEndAddress()); + fflush(NULL); if (myArea->contains(address)) return myArea; } diff --git a/src/kernel/vm2/page.h b/src/kernel/vm2/page.h index 400067363c..9a886e9793 100644 --- a/src/kernel/vm2/page.h +++ b/src/kernel/vm2/page.h @@ -7,8 +7,10 @@ class page : public node { void *cpuSpecific; void *physicalAddress; public: - page(void *address) : physicalAddress(address) {} ; + int count; + page(void *address) : physicalAddress(address) {count=0;} ; void zero(void); unsigned long getAddress(void) {return (unsigned long)physicalAddress;} + void dump(void) { printf ("Page %x, physicalAddress = %x\n",this,getAddress()); } }; #endif diff --git a/src/kernel/vm2/pageManager.C b/src/kernel/vm2/pageManager.C index 826d7905ee..3960e387be 100644 --- a/src/kernel/vm2/pageManager.C +++ b/src/kernel/vm2/pageManager.C @@ -15,9 +15,11 @@ pageManager::pageManager(int pages) printf ("pageManager::pageManager: No memory!\n"); exit(1); } + printf ("Allocated an area. Address = %x\n",area); for (int i=0;izero(); - } // This could fail if someone swoops in and steal our page. + } // This could fail if someone swooped in and stole our page. if (ret) { acquire_sem(inUseLock); inUse.add(ret); release_sem(inUseLock); + ret->count++; } - //printf ("pageManager::getPage:leaving with page = %x\n", ret); +// printf ("pageManager::getPage:leaving with page = %x\n", ret->getAddress()); return ret; } void pageManager::freePage(page *toFree) { - acquire_sem(inUseLock); - inUse.remove(toFree); - release_sem(inUseLock); - acquire_sem(unusedLock); - unused.add(toFree); - release_sem(unusedLock); +// 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) + { + acquire_sem(inUseLock); + inUse.remove(toFree); + release_sem(inUseLock); + acquire_sem(unusedLock); + unused.add(toFree); + release_sem(unusedLock); + } } void pageManager::cleaner(void) @@ -98,7 +107,32 @@ void pageManager::cleaner(void) int pageManager::desperation(void) { // Formula to determine how desperate system is to get pages back... - int percentClean=(unused.count()+clean.count())/totalPages; + int percentClean=(unused.count()+clean.count())*100/totalPages; if (percentClean>30) return 1; - return (35-percentClean)/5; + return (35-percentClean)/7; } + +void pageManager::dump(void) +{ + printf ("Dumping the unused list\n"); + for (struct node *cur=unused.rock;cur;) + { + page *thisPage=(page *)cur; + thisPage->dump(); + cur=cur->next; + } + printf ("Dumping the clean list\n"); + for (struct node *cur=clean.rock;cur;) + { + page *thisPage=(page *)cur; + thisPage->dump(); + cur=cur->next; + } + printf ("Dumping the inuse list\n"); + for (struct node *cur=inUse.rock;cur;) + { + page *thisPage=(page *)cur; + thisPage->dump(); + cur=cur->next; + } +} diff --git a/src/kernel/vm2/pageManager.h b/src/kernel/vm2/pageManager.h index 43e8dbf62b..6e7d2a1014 100644 --- a/src/kernel/vm2/pageManager.h +++ b/src/kernel/vm2/pageManager.h @@ -11,6 +11,7 @@ class pageManager { void freePage(page *); void cleaner(void); int desperation(void); + void dump(void); private: list clean,unused,inUse; sem_id cleanLock,unusedLock,inUseLock; diff --git a/src/kernel/vm2/swapFileManager.C b/src/kernel/vm2/swapFileManager.C index cac8f6b945..f72fdffc0c 100644 --- a/src/kernel/vm2/swapFileManager.C +++ b/src/kernel/vm2/swapFileManager.C @@ -13,12 +13,13 @@ swapFileManager::swapFileManager(void) void swapFileManager::write_block(vnode &node,void *loc,unsigned long size) { - printf ("swapFileManager::write_block: writing, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc); + //printf ("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)) printf ("seek failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno)); if (-1==write(node.fd,loc,size)) printf ("Write failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno)); node.valid=true; + //printf ("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) @@ -26,7 +27,7 @@ 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\n",node.fd, node.offset); + //printf ("swapFileManager::read_block: reading, node.fd = %d, node.offset = %d into %x\n",node.fd, node.offset,loc); read(node.fd,loc,size); } @@ -36,30 +37,37 @@ vnode &swapFileManager::findNode(void) //swapFileFreeList.dump(); //printf ("swapFileManager::findNode: Finding a new node for you, Master: "); vnode *newNode; + //printf ("locking in sfm\n"); Lock(); - if (newNode=reinterpret_cast(swapFileFreeList.next())) - { - //printf (" Reused: %d\n",newNode->offset); - } - else + newNode=reinterpret_cast(swapFileFreeList.next()); + //printf ("unlocking in sfm\n"); + Unlock(); + if (!newNode) { newNode=new vnode; newNode->fd=swapFile; newNode->offset=maxNode+=PAGE_SIZE; - newNode->valid=false; //printf (" New One: %d\n",newNode->offset); } - Unlock(); + newNode->valid=false; + newNode->count=0; //printf ("swapFileManager::findNode: swapFileFreeList is now: "); //swapFileFreeList.dump(); + newNode->count++; return *newNode; } void swapFileManager::freeVNode(vnode &v) { - Lock(); - //printf ("swapFileManager::freeNode: Starting Freeing a new node for you, Master: offset:%d\n",v.offset); - v.valid=false; - swapFileFreeList.add(&v); - Unlock(); + v.count--; + if (v.count==0) + { + //printf ("locking in sfm\n"); + Lock(); + //printf ("swapFileManager::freeNode: Starting Freeing a new node for you, Master: offset:%d\n",v.offset); + v.valid=false; + swapFileFreeList.add(&v); + //printf ("unlocking in sfm\n"); + Unlock(); + } } diff --git a/src/kernel/vm2/test.C b/src/kernel/vm2/test.C index ca7c654821..4d62637790 100644 --- a/src/kernel/vm2/test.C +++ b/src/kernel/vm2/test.C @@ -5,7 +5,7 @@ #include #include -vmInterface vm(20); +vmInterface vm(30); void writeByte(unsigned long addr,unsigned int offset, char value) { vm.setByte(addr+offset,value); } @@ -13,15 +13,24 @@ unsigned char readByte(unsigned long addr,unsigned int offset ) { char value=vm. int createFillAndTest(int pages) { + try{ unsigned long addr; int area1; area1=vm.createArea("Mine",pages,(void **)(&addr)); + printf ("createFillAndTest: create done\n"); for (int i=0;iinitialSnooze); - //printf ("Creating %s area\n",params->name); + printf ("Creating %s area\n",params->name); area1=createFillAndTest(params->areaSize); snooze(params->holdSnooze); - //printf ("Freeing %s area\n",params->name); + printf ("Freeing %s area\n",params->name); vm.freeArea(area1); snooze(params->loopSnooze); } @@ -85,13 +95,13 @@ int32 mmapTest (void *parameters) { void *map; - int fd = open ("OBOS_mmap",O_RDWR|O_CREAT,0x777); - printf ("Opened file, fd = %d\n",fd); loopTestParameters *params=((loopTestParameters *)parameters); int size=params->areaSize; // Note that this is in bytes, not in pages -// while (1) + while (1) { + int fd = open ("OBOS_mmap",O_RDWR|O_CREAT,0x777); + printf ("Opened file, fd = %d\n",fd); snooze(params->initialSnooze); printf ("Creating %s mmap\n",params->name); snooze(params->holdSnooze); @@ -102,12 +112,37 @@ int32 mmapTest (void *parameters) for (int i=0;iloopSnooze); - } + snooze(params->loopSnooze); + vm.munmap(map,size); close(fd); - printf ("Closed file, fd = %d\n",fd); + printf ("Closed file, fd = %d\n",fd); + } } +int32 cloneTest (void *parameters) + { + loopTestParameters *params=((loopTestParameters *)parameters); + int area1,area2; + void *cloneAddr=NULL; + + while (1) + { + snooze(params->initialSnooze); + // printf ("Creating %s area, size = %d\n",params->name,params->areaSize); + area1=createFillAndTest(params->areaSize); + // 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 ("Snoozing, compare done \n"); + snooze(params->holdSnooze); + // printf ("Freeing %s area\n",params->name); + vm.freeArea(area2); + vm.freeArea(area1); + snooze(params->loopSnooze); + } + } int main(int argc,char **argv) { @@ -116,14 +151,16 @@ int main(int argc,char **argv) loopTestParameters area3Params={"area3",1000000,2,300000,200000}; loopTestParameters info1Params={"info1",500000,2,400000,30000}; loopTestParameters mmap1Params={"mmap",500000,8192,400000,1000000}; + loopTestParameters clone1Params={"clone1",200000,2,300000,400000}; //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)); - snooze(10000000); + snooze(1000000000); return 0; } diff --git a/src/kernel/vm2/vm.h b/src/kernel/vm2/vm.h index 1d4b9af0b7..c3b88fda6c 100644 --- a/src/kernel/vm2/vm.h +++ b/src/kernel/vm2/vm.h @@ -8,6 +8,13 @@ struct vnode : public node int fd; unsigned long offset; bool valid; + int count; + + vnode (void) + { + valid=false; + count=0; + } }; typedef unsigned long owningProcess; #define B_OS_NAME_LENGTH 32 diff --git a/src/kernel/vm2/vmInterface.C b/src/kernel/vm2/vmInterface.C index 5608b70ab7..c0481e7b2f 100644 --- a/src/kernel/vm2/vmInterface.C +++ b/src/kernel/vm2/vmInterface.C @@ -1,6 +1,7 @@ #include "vmInterface.h" //#include "areaManager.h" #include "mman.h" +#include "area.h" areaManager am; swapFileManager swapMan; @@ -30,11 +31,22 @@ int32 saverThread(void *areaMan) } } +int32 pagerThread(void *areaMan) + { + areaManager *am=(areaManager *)areaMan; + while (1) + { + snooze(1000000); + am->pager(pageMan.desperation()); + } + } + vmInterface::vmInterface(int pages) { nextAreaID=0; resume_thread(spawn_thread(cleanerThread,"cleanerThread",0,&pageMan)); resume_thread(spawn_thread(saverThread,"saverThread",0,getAM())); + resume_thread(spawn_thread(pagerThread,"pagerThread",0,getAM())); } int vmInterface::getAreaByAddress(void *address) @@ -104,9 +116,13 @@ status_t vmInterface::getAreaInfo(int Area,area_info *dest) } status_t vmInterface::getNextAreaInfo(int process,int32 *cookie,area_info *dest) - // Left for later.. { - ; + area *oldArea=getAM()->findArea(*cookie); + area *newArea=(area *)(oldArea->next); + if (newArea) + return newArea->getInfo(dest); + else + return B_BAD_VALUE; } int vmInterface::getAreaByName(char *name) @@ -114,9 +130,14 @@ int vmInterface::getAreaByName(char *name) return getAM()->findArea(name)->getAreaID(); } -int vmInterface::cloneArea(int area,char *AreaName,void **address, addressSpec addType=ANY, pageState state=NO_LOCK, protectType prot=writable) +int vmInterface::cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType=ANY, pageState state=NO_LOCK, protectType prot=writable) { - ; + area *newArea = new area(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(); } void vmInterface::pager(void) @@ -154,7 +175,7 @@ void *vmInterface::mmap(void *addr, size_t len, int prot, int flags, int fd, off 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); + //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); @@ -162,11 +183,20 @@ void *vmInterface::mmap(void *addr, size_t len, int prot, int flags, int fd, off } area *newArea = new area(getAM()); - printf ("area = %x, start = %x\n",newArea, newArea->getStartAddress()); + //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; - } + +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(); +} diff --git a/src/kernel/vm2/vmInterface.h b/src/kernel/vm2/vmInterface.h index feb896495f..b18488e7b0 100644 --- a/src/kernel/vm2/vmInterface.h +++ b/src/kernel/vm2/vmInterface.h @@ -24,6 +24,7 @@ class vmInterface // This is the class that "owns" all of the managers. status_t resizeArea(int area,size_t size); status_t setAreaProtection(int area,protectType prot); void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset); + status_t munmap(void *addr, size_t len); void pager(void); void saver(void); void cleaner(void); diff --git a/src/kernel/vm2/vpage.C b/src/kernel/vm2/vpage.C index 4d6c55fbe7..8a0dd465a3 100644 --- a/src/kernel/vm2/vpage.C +++ b/src/kernel/vm2/vpage.C @@ -11,36 +11,42 @@ void vpage::flush(void) void vpage::refresh(void) { - swapMan.read_block(*backingNode,physPage, PAGE_SIZE); - } - -vpage *vpage::clone(unsigned long address) // The calling method will have to create this... - { - return new vpage(address,NULL,physPage,(protection==readable)?protection:copyOnWrite,LAZY); // Not sure if LAZY is right or not + swapMan.read_block(*backingNode,((void *)(physPage->getAddress())), PAGE_SIZE); } // backing and/or physMem can be NULL/0. vpage::vpage(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state) { + //printf ("vpage::vpage: start = %x, vnode.fd=%d, vnode.offset=%d, physMem = %x\n",start,((backing)?backing->fd:0),((backing)?backing->offset:0), ((physMem)?(physMem->getAddress()):0)); start_address=start; end_address=start+PAGE_SIZE-1; protection=prot; swappable=(state==NO_LOCK); + dirty=true; + if (backing) + { backingNode=backing; + backing->count++; + } else backingNode=&(swapMan.findNode()); - if (!physPage && (state!=LAZY) && (state!=NO_LOCK)) + if (!physMem && (state!=LAZY) && (state!=NO_LOCK)) physPage=pageMan.getPage(); else + { + if (physMem) + physMem->count++; physPage=physMem; + } + //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)); } vpage::~vpage(void) { - if (physPage) // I doubt that this is always true. Probably need to check for sharing... + if (physPage) // Note that free means release one reference pageMan.freePage(physPage); - if (backingNode->fd) + if (backingNode->fd) swapMan.freeVNode(*backingNode); } @@ -52,7 +58,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 = %x, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false")); if (writeError) { dirty=true; @@ -61,6 +67,8 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa if (protection==copyOnWrite) // Else, this was just a "let me know when I am dirty"... { page *newPhysPage=pageMan.getPage(); + if (!newPhysPage) // No room at the inn + return false; memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE); physPage=newPhysPage; protection=writable; @@ -71,12 +79,17 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa } } physPage=pageMan.getPage(); - printf ("vpage::fault: New page allocated! new physical address = %x\n",physPage->getAddress()); + if (!physPage) // No room at the inn + return false; +// printf ("vpage::fault: New page allocated! new physical address = %x vnode.fd=%d, vnode.offset=%d, \n",physPage->getAddress(),((backingNode)?backingNode->fd:0),((backingNode)?backingNode->offset:0)); // Update the architecture specific stuff here... // This refresh is unneeded if the data was never written out... +// dump(); refresh(); // I wonder if these vnode calls are safe during an interrupt... - printf ("vpage::fault: Refreshed\n"); - +// printf ("vpage::fault: Refreshed\n"); +// dump(); +// printf ("vpage::fault: exiting\n"); + return true; } char vpage::getByte(unsigned long address) @@ -117,8 +130,10 @@ void vpage::setInt(unsigned long address,int value) void vpage::pager(int desperation) { + printf ("vpage::pager start desperation = %d\n",desperation); if (!swappable) return; + printf ("vpage::pager swappable\n"); switch (desperation) { case 1: return; break; @@ -128,8 +143,11 @@ void vpage::pager(int desperation) case 5: if (!physPage) return;break; default: return;break; } + printf ("vpage::pager flushing\n"); flush(); + printf ("vpage::pager freeing\n"); pageMan.freePage(physPage); + printf ("vpage::pager going to NULL\n"); physPage=NULL; } diff --git a/src/kernel/vm2/vpage.h b/src/kernel/vm2/vpage.h index 9ee6a55414..35f6a8d05e 100644 --- a/src/kernel/vm2/vpage.h +++ b/src/kernel/vm2/vpage.h @@ -17,20 +17,27 @@ class vpage : public node bool contains(uint32 address) { return ((start_address<=address) && (end_address>=address)); } void flush(void); // write page to vnode, if necessary void refresh(void); // Read page back in from vnode - vpage *clone(unsigned long); // Make a new vpage that is exactly the same as this one. - // If we are read only, it is read only. - // If we are read/write, both pages are copy on write vpage(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state); // backing and/or physMem can be NULL/0. ~vpage(void); void setProtection(protectType prot); protectType getProtection(void) {return protection;} void *getStartAddress(void) {return (void *)start_address;} + page *getPhysPage(void) {return physPage;} + vnode *getBacking(void) {return backingNode;} bool fault(void *fault_address, bool writeError); // true = OK, false = panic. void pager(int desperation); void saver(void); + void dump(void) + { + printf ("Dumping vpage %x, address = %x, \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