From 72515139f759ec75f77f203add1a505aa51deeb3 Mon Sep 17 00:00:00 2001 From: Michael Phipps Date: Thu, 25 Jul 2002 01:27:00 +0000 Subject: [PATCH] Updates to make creating areas and accessing bytes work. Lots of debugging printfs, etc in here. But some bug fixes and better code. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@426 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/vm2/area.C | 35 +++++++++++++++++++++++++++++++- src/kernel/vm2/areaManager.C | 3 +++ src/kernel/vm2/areaManager.h | 3 +++ src/kernel/vm2/cacheManager.C | 3 +++ src/kernel/vm2/cacheManager.h | 3 +++ src/kernel/vm2/list.h | 4 ++-- src/kernel/vm2/pageManager.C | 12 ++++++++--- src/kernel/vm2/swapFileManager.C | 7 +++++-- src/kernel/vm2/test.C | 8 ++++++-- src/kernel/vm2/vm.h | 2 +- src/kernel/vm2/vmInterface.C | 6 ++++-- src/kernel/vm2/vmInterface.h | 10 ++++++--- src/kernel/vm2/vpage.C | 35 ++++++++++++++++++++------------ src/kernel/vm2/vpage.h | 4 +--- 14 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/kernel/vm2/area.C b/src/kernel/vm2/area.C index 1397d171ec..fc3ed20c3b 100644 --- a/src/kernel/vm2/area.C +++ b/src/kernel/vm2/area.C @@ -9,6 +9,7 @@ area::area (areaManager *myManager) unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount) { + // We will lock in the callers unsigned long base; switch (type) { @@ -33,6 +34,7 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque status_t area::createAreaMappingFile(char *name, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset) { + manager->lock(); unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works... unsigned long base=mapAddressSpecToAddress(type,requested,pageCount); vpage *newPage; @@ -45,36 +47,51 @@ status_t area::createAreaMappingFile(char *name, int pageCount,void **address, a vpages.add(newPage); } state=inState; + start_address=base; + end_address=base+pageCount*PAGE_SIZE; + manager->unlock(); } status_t area::createArea(char *name, int pageCount,void **address, addressSpec type,pageState inState,protectType protect) { + manager->lock(); + printf ("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 ("in area::createArea, base address = %d\n",base); vpage *newPage; vnode newVnode; newVnode.fd=0; newVnode.offset=0; for (int i=0;iunlock(); + *address=(void *)base; + printf ("unlocked in createArea\n"); } void area::freeArea(void) { + manager->lock(); for (struct node *cur=vpages.rock;cur;cur=cur->next) { vpage *page=(vpage *)cur; page->flush(); delete page; // Probably need to add a destructor } + manager->unlock(); } status_t area::getInfo(area_info *dest) { + // no need to lock here... strcpy(dest->name,name); dest->size=end_address-start_address; dest->lock=state; @@ -98,8 +115,11 @@ status_t area::getInfo(area_info *dest) bool area::contains(void *address) { + // no need to lock here... unsigned long base=(unsigned long)(address); - return ((start_address>=base) && (end_address<=base)); + printf ("Inside 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)); } status_t area::resize(size_t newSize) @@ -109,6 +129,7 @@ status_t area::resize(size_t newSize) return B_OK; if (newSize>oldSize) { + manager->lock(); int pageCount = (newSize-oldSize) / PAGE_SIZE; vpage *newPage; vnode newVnode; @@ -123,6 +144,7 @@ status_t area::resize(size_t newSize) } else { + manager->lock(); int pageCount = (oldSize -newSize) / PAGE_SIZE; vpage *oldPage; struct node *cur; @@ -133,20 +155,24 @@ status_t area::resize(size_t newSize) delete oldPage; } } + manager->unlock(); } 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(); } vpage *area::findVPage(unsigned long address) { + // No need to lock here... for (struct node *cur=vpages.rock;cur;cur=cur->next) { vpage *page=(vpage *)cur; @@ -158,6 +184,7 @@ vpage *area::findVPage(unsigned long address) bool area::fault(void *fault_address, bool writeError) // true = OK, false = panic. { + // No need to lock here... vpage *page=findVPage((unsigned long)fault_address); if (page) return page->fault(fault_address,writeError); @@ -167,6 +194,7 @@ bool area::fault(void *fault_address, bool writeError) // true = OK, false = pan char area::getByte(unsigned long address) // This is for testing only { + // No need to lock here... vpage *page=findVPage(address); if (page) return page->getByte(address); @@ -176,6 +204,7 @@ char area::getByte(unsigned long address) // This is for testing only void area::setByte(unsigned long address,char value) // This is for testing only { + // No need to lock here... vpage *page=findVPage(address); if (page) page->setByte(address,value); @@ -183,6 +212,7 @@ void area::setByte(unsigned long address,char value) // This is for testing only int area::getInt(unsigned long address) // This is for testing only { + // No need to lock here... vpage *page=findVPage(address); if (page) page->getInt(address); @@ -190,6 +220,7 @@ int area::getInt(unsigned long address) // This is for testing only void area::setInt(unsigned long address,int value) // This is for testing only { + // No need to lock here... vpage *page=findVPage(address); if (page) page->setInt(address,value); @@ -197,6 +228,7 @@ void area::setInt(unsigned long address,int value) // This is for testing only void area::pager(int desperation) { + // No need to lock here... for (struct node *cur=vpages.rock;cur;cur=cur->next) { vpage *page=(vpage *)cur; @@ -206,6 +238,7 @@ void area::pager(int desperation) void area::saver(void) { + // No need to lock here... for (struct node *cur=vpages.rock;cur;cur=cur->next) { vpage *page=(vpage *)cur; diff --git a/src/kernel/vm2/areaManager.C b/src/kernel/vm2/areaManager.C index 3dbeff85cb..4843a41faf 100644 --- a/src/kernel/vm2/areaManager.C +++ b/src/kernel/vm2/areaManager.C @@ -3,6 +3,7 @@ areaManager::areaManager(void) { team=0; // should be proc_get_current_proc_id() + myLock=create_sem(1,"Area Manager Semaphore"); // Should have team name in it. } unsigned long areaManager::getNextAddress(int pages, unsigned long start) @@ -39,9 +40,11 @@ area *areaManager::findArea(void *address) for (struct node *cur=areas.rock;cur;cur=cur->next) { area *myArea=(area *)cur; + printf ("Looking for %d\n",address); if (myArea->contains(address)) return myArea; } + printf ("findArea is giving up\n"); return NULL; } diff --git a/src/kernel/vm2/areaManager.h b/src/kernel/vm2/areaManager.h index 88585113e5..c2d13f50f5 100644 --- a/src/kernel/vm2/areaManager.h +++ b/src/kernel/vm2/areaManager.h @@ -5,6 +5,7 @@ class areaManager // One of these per process private: list areas; team_id team; + sem_id myLock; public: areaManager (); void addArea(area *newArea) {areas.add(newArea);} @@ -16,6 +17,8 @@ class areaManager // One of these per process area *findArea(area_id id); void pager(int desperation); void saver(void); + void lock() {acquire_sem(myLock);} + void unlock() {release_sem(myLock);} bool fault(void *fault_address, bool writeError); // true = OK, false = panic. diff --git a/src/kernel/vm2/cacheManager.C b/src/kernel/vm2/cacheManager.C index d24b30f420..96cabe20cc 100644 --- a/src/kernel/vm2/cacheManager.C +++ b/src/kernel/vm2/cacheManager.C @@ -2,6 +2,7 @@ cacheManager::cacheManager(void) : area (NULL) { + myLock=create_sem(1,"Area Manager Semaphore"); // Should have team name in it. } void *cacheManager::findBlock(vnode *target,bool readOnly) @@ -30,10 +31,12 @@ void *cacheManager::createBlock(vnode *target,bool readOnly) begin+=PAGE_SIZE; prev=cur; } + lock(); // Create a vnode here vpage *newPage = new vpage(begin,*target,NULL,((readOnly)?readable:writable),NO_LOCK); vpages.add(newPage); cacheMembers.add(newPage); + unlock(); // return address from this vnode return (void *)begin; diff --git a/src/kernel/vm2/cacheManager.h b/src/kernel/vm2/cacheManager.h index ab7e99d042..244bd03793 100644 --- a/src/kernel/vm2/cacheManager.h +++ b/src/kernel/vm2/cacheManager.h @@ -17,6 +17,7 @@ class cacheManager : public area // 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); void *createBlock (vnode *target,bool readOnly); + sem_id myLock; public: // For these two, the VFS passes in the target vnode // Return value is the address. Note that the paging daemon does the actual loading @@ -25,4 +26,6 @@ class cacheManager : public area void *writeBlock (vnode *target); void pager(int desperation); // override, as we should blow away useless nodes, not just free blocks. void saver(void); // Override - not sure why + void lock() {acquire_sem(myLock);} + void unlock() {release_sem(myLock);} }; diff --git a/src/kernel/vm2/list.h b/src/kernel/vm2/list.h index 12b8ace04d..48bca10d74 100644 --- a/src/kernel/vm2/list.h +++ b/src/kernel/vm2/list.h @@ -19,7 +19,7 @@ class list { rock=newNode; nodeCount++; } - int count(void) {return nodeCount;} + int count(void) {printf ("About to return %d\n",nodeCount);return nodeCount;} void *next(void) {nodeCount--;node *n=rock;if (rock) rock=rock->next;return rock;} void remove(void *in) { @@ -39,7 +39,7 @@ class list { } } struct node *rock; - private: int nodeCount; + private: }; #endif diff --git a/src/kernel/vm2/pageManager.C b/src/kernel/vm2/pageManager.C index d7b22777c0..b8bf08efb4 100644 --- a/src/kernel/vm2/pageManager.C +++ b/src/kernel/vm2/pageManager.C @@ -27,20 +27,26 @@ pageManager::pageManager(int pages) page *pageManager::getPage(void) { page *ret=NULL; -// printf ("Checking clean\n"); + printf ("Checking clean\n"); + printf ("clean = %d\n", &clean); + printf ("cleanCount = %d\n", clean.nodeCount); if (clean.count()) { + printf ("locking clean\n"); acquire_sem(cleanLock); + printf ("locked clean\n"); ret=(page *)clean.next(); + printf ("got next clean\n"); release_sem(cleanLock); + printf ("unlocked clean\n"); } // This could fail if someone swoops in and steal our page. if (!ret && unused.count()) { -// printf ("Checking unused\n"); + printf ("Checking unused\n"); acquire_sem(unusedLock); ret=(page *)unused.next(); release_sem(unusedLock); -// printf ("ret = %x\n",ret); + printf ("ret = %x\n",ret); if (ret) ret->zero(); } // This could fail if someone swoops in and steal our page. diff --git a/src/kernel/vm2/swapFileManager.C b/src/kernel/vm2/swapFileManager.C index fc6ef372b6..9654fe128f 100644 --- a/src/kernel/vm2/swapFileManager.C +++ b/src/kernel/vm2/swapFileManager.C @@ -1,25 +1,28 @@ #include "swapFileManager.h" -//#include +#include swapFileManager::swapFileManager(void) { - swapFile = open("/tmp/OBOS_swap",O_RDWR ); + swapFile = open("/boot/var/tmp/OBOS_swap",O_RDWR ); } void swapFileManager::write_block(vnode node,void *loc,unsigned long size) { + printf ("writing, node.fd = %d, node.offset = %d\n",node.fd, node.offset); lseek(node.fd,SEEK_SET,node.offset); write(node.fd,loc,size); } void swapFileManager::read_block(vnode node,void *loc,unsigned long size) { + printf ("reading, node.fd = %d, node.offset = %d\n",node.fd, node.offset); lseek(node.fd,SEEK_SET,node.offset); read(node.fd,loc,size); } vnode swapFileManager::findNode(void) { + printf ("Finding a new node for you master\n"); vnode tmp; tmp.fd=swapFile; tmp.offset=maxNode+=PAGE_SIZE; // Can't ever free, swap file grows forever... :-( diff --git a/src/kernel/vm2/test.C b/src/kernel/vm2/test.C index feca0ab811..6fc2dab0a3 100644 --- a/src/kernel/vm2/test.C +++ b/src/kernel/vm2/test.C @@ -5,7 +5,11 @@ int main(int argc,char **argv) { vmInterface vm(10); - void *addr; - vm.createArea("Mine",1,&addr); + unsigned long addr; + vm.createArea("Mine",2,(void **)(&addr)); + printf ("addr = %d\n",addr); + vm.setByte(addr,99); + printf ("addr = %d\n",addr); + printf ("Byte = %d\n",vm.getByte(addr)); return 0; } diff --git a/src/kernel/vm2/vm.h b/src/kernel/vm2/vm.h index 80a0b45b25..b300edffdd 100644 --- a/src/kernel/vm2/vm.h +++ b/src/kernel/vm2/vm.h @@ -12,7 +12,7 @@ typedef unsigned long owningProcess; enum protectType {none=0,readable, writable,copyOnWrite,symCopyOnWrite}; enum pageState {FULL,CONTIGUOUS,LAZY,NO_LOCK,LOMEM}; enum addressSpec {EXACT,BASE,ANY,ANY_KERNEL,CLONE}; -#define USER_BASE 0 +#define USER_BASE 0x10000000 #define KERNEL_BASE 0x80000000 #define CACHE_BEGIN 0x90000000 #define CACHE_END 0xe0000000 diff --git a/src/kernel/vm2/vmInterface.C b/src/kernel/vm2/vmInterface.C index 55f61029d8..e55bd1d61f 100644 --- a/src/kernel/vm2/vmInterface.C +++ b/src/kernel/vm2/vmInterface.C @@ -1,10 +1,12 @@ #include "vmInterface.h" -#include "areaManager.h" +//#include "areaManager.h" #include "mman.h" areaManager am; +swapFileManager swapMan; +pageManager pageMan(10); // Obviously this hard coded number is a hack... -areaManager *getAM(void) +areaManager *vmInterface::getAM(void) { // Normally, we would go to the current user process to get this. Since there no such thing exists here... return &am; diff --git a/src/kernel/vm2/vmInterface.h b/src/kernel/vm2/vmInterface.h index f4e9d90ce7..b8b212c6d1 100644 --- a/src/kernel/vm2/vmInterface.h +++ b/src/kernel/vm2/vmInterface.h @@ -1,14 +1,14 @@ #include "vm.h" #include "pageManager.h" +#include "areaManager.h" #include "swapFileManager.h" class vmInterface // This is the class that "owns" all of the managers. { private: - swapFileManager swapMan; - pageManager pageMan; int nextAreaID; + areaManager *getAM(void); // This is for testing only... public: - vmInterface(int pages) : pageMan(pages) {nextAreaID=0;}; + vmInterface(int pages) {nextAreaID=0;}; int createArea(char *AreaName,int pageCount,void **address, addressSpec addType=ANY, pageState state=NO_LOCK,protectType protect=writable); @@ -27,4 +27,8 @@ class vmInterface // This is the class that "owns" all of the managers. void pager(void); void saver(void); void cleaner(void); + 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 + void setInt(unsigned long offset,int value) {getAM()->setByte(offset,value);} // This is for testing only }; diff --git a/src/kernel/vm2/vpage.C b/src/kernel/vm2/vpage.C index bdbbb25345..27b5644dc5 100644 --- a/src/kernel/vm2/vpage.C +++ b/src/kernel/vm2/vpage.C @@ -1,17 +1,17 @@ #include "vpage.h" - swapFileManager *vpage::swapMan; - pageManager *vpage::pageMan; + extern swapFileManager swapMan; + extern pageManager pageMan; void vpage::flush(void) { if (protection==writable && dirty) - swapMan->write_block(backingNode,physPage, PAGE_SIZE); + swapMan.write_block(backingNode,physPage, PAGE_SIZE); } void vpage::refresh(void) { - swapMan->read_block(backingNode,physPage, PAGE_SIZE); + swapMan.read_block(backingNode,physPage, PAGE_SIZE); } vpage *vpage::clone(unsigned long address) // The calling method will have to create this... @@ -29,12 +29,12 @@ vpage::vpage(unsigned long start,vnode backing, page *physMem,protectType prot,p end_address=start+PAGE_SIZE-1; protection=prot; swappable=(state==NO_LOCK); - if (backing.fd=0) - backingNode=swapMan->findNode(); + if (backing.fd==0) + backingNode=swapMan.findNode(); else backingNode=backing; if (!physPage && (state!=LAZY) && (state!=NO_LOCK)) - physPage=pageMan->getPage(); + physPage=pageMan.getPage(); else physPage=physMem; } @@ -47,6 +47,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 ("Inside fault; address = %d, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false")); if (writeError) { dirty=true; @@ -54,33 +55,41 @@ 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(); + page *newPhysPage=pageMan.getPage(); memcpy(newPhysPage,physPage,PAGE_SIZE); physPage=newPhysPage; protection=writable; - backingNode=swapMan->findNode(); // Need new backing store for this node, since it was copied, the original is no good... + backingNode=swapMan.findNode(); // Need new backing store for this node, since it was copied, the original is no good... // Update the architecture specific stuff here... } return true; } } - physPage=pageMan->getPage(); + physPage=pageMan.getPage(); + printf ("New page allocated! address = %s\n",physPage->getAddress()); // Update the architecture specific stuff here... + // This refresh is unneeded if the code was never written out... refresh(); // I wonder if these vnode calls are safe during an interrupt... + printf ("Refreshed\n"); + } char vpage::getByte(unsigned long address) { + printf ("inside vpage::getByte; address = %d\n",address ); if (!physPage) fault((void *)(address),false); + printf ("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) { + printf ("inside vpage::setByte; address = %d, value = %d\n",address, value); if (!physPage) - fault((void *)(address),false); + fault((void *)(address),true); *((char *)(address-start_address+physPage->getAddress()))=value; + printf ("inside vpage::setByte; physical address = %d, value = %d\n",physPage->getAddress(), *((char *)(physPage->getAddress()))); } int vpage::getInt(unsigned long address) @@ -93,7 +102,7 @@ int vpage::getInt(unsigned long address) void vpage::setInt(unsigned long address,int value) { if (!physPage) - fault((void *)(address),false); + fault((void *)(address),true); *((int *)(address-start_address+physPage->getAddress()))=value; } @@ -111,7 +120,7 @@ void vpage::pager(int desperation) default: return;break; } flush(); - pageMan->freePage(physPage); + pageMan.freePage(physPage); physPage=NULL; } diff --git a/src/kernel/vm2/vpage.h b/src/kernel/vm2/vpage.h index 02007dec14..9b43541cf5 100644 --- a/src/kernel/vm2/vpage.h +++ b/src/kernel/vm2/vpage.h @@ -14,7 +14,7 @@ class vpage : public node unsigned long end_address; public: bool isMapped(void) {return (physPage);} - bool contains(uint32 address) { return ((start_address>=address) && (end_address<=address)); } + 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. @@ -34,6 +34,4 @@ class vpage : public node 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 - static swapFileManager *swapMan; - static pageManager *pageMan; };