From 7bebb1dec30ee8ccad461e1b9cb6caf11dc55315 Mon Sep 17 00:00:00 2001 From: Michael Phipps Date: Wed, 7 Aug 2002 03:21:02 +0000 Subject: [PATCH] Just to make Daniel happy... ;-) swapfile blocks are now put on a free list and properly reused, so it no longer grows out of control. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@626 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/vm2/area.C | 30 +++++++++------------- src/kernel/vm2/cacheManager.C | 2 +- src/kernel/vm2/list.h | 27 +++++++++++++++----- src/kernel/vm2/pageManager.C | 6 ++--- src/kernel/vm2/swapFileManager.C | 43 +++++++++++++++++++++++--------- src/kernel/vm2/swapFileManager.h | 18 ++++++++----- src/kernel/vm2/vm.h | 5 ++-- src/kernel/vm2/vmInterface.C | 12 ++++----- src/kernel/vm2/vpage.C | 23 ++++++++--------- src/kernel/vm2/vpage.h | 4 +-- 10 files changed, 101 insertions(+), 69 deletions(-) diff --git a/src/kernel/vm2/area.C b/src/kernel/vm2/area.C index 8b2587832e..943e0ef6cf 100644 --- a/src/kernel/vm2/area.C +++ b/src/kernel/vm2/area.C @@ -38,11 +38,11 @@ status_t area::createAreaMappingFile(char *name, int pageCount,void **address, a unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works... unsigned long base=mapAddressSpecToAddress(type,requested,pageCount); vpage *newPage; - vnode newVnode; + vnode *newVnode=new vnode; for (int i=0;ifd=fd; + newVnode->offset=offset+PAGE_SIZE*i; newPage = new vpage(base+PAGE_SIZE*i,newVnode,NULL,protect,inState); vpages.add(newPage); } @@ -55,18 +55,15 @@ status_t area::createAreaMappingFile(char *name, int pageCount,void **address, a status_t area::createArea(char *name, int pageCount,void **address, addressSpec type,pageState inState,protectType protect) { manager->lock(); - printf ("area::createArea: Locked in createArea\n"); + //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); + //printf ("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 ("area::createArea: unlocked in createArea\n"); + //printf ("area::createArea: unlocked in createArea\n"); } void area::freeArea(void) { - printf ("area::freeArea: starting \n"); + //printf ("area::freeArea: starting \n"); manager->lock(); - vpages.dump(); +// vpages.dump(); for (struct node *cur=vpages.rock;cur;) { //printf ("area::freeArea: wasting a page: %x\n",cur); @@ -94,7 +91,7 @@ void area::freeArea(void) } //printf ("area::freeArea: unlocking \n"); manager->unlock(); - printf ("area::freeArea: ending \n"); + //printf ("area::freeArea: ending \n"); } status_t area::getInfo(area_info *dest) @@ -140,12 +137,9 @@ status_t area::resize(size_t newSize) manager->lock(); int pageCount = (newSize-oldSize) / PAGE_SIZE; vpage *newPage; - vnode newVnode; - newVnode.fd=0; - newVnode.offset=0; for (int i=0;i(in); newNode->next=rock; rock=newNode; nodeCount++; } //int count(void) {printf ("list::count: About to return %d\n",nodeCount);return nodeCount;} int count(void) {return nodeCount;} - void *next(void) {nodeCount--;node *n=rock;if (rock) rock=rock->next;return n;} + node *next(void) + { + //dump(); + node *n=rock; + if (rock) + { + rock=rock->next; + nodeCount--; + } + //dump(); + return n; + } void remove(node *toNuke) { -// printf ("list::remove starting: nuking %x \n",toNuke); -// list::dump(); + //printf ("list::remove starting: nuking %x \n",toNuke); + //dump(); if (rock==toNuke) + { rock=rock->next; + nodeCount--; + } else { bool done=false; @@ -35,11 +49,12 @@ class list { if (cur->next==toNuke) { cur->next=toNuke->next; + nodeCount--; done=true; } } -// printf ("list::remove ending: \n"); -// list::dump(); + //printf ("list::remove ending: \n"); + //dump(); } void dump(void) { diff --git a/src/kernel/vm2/pageManager.C b/src/kernel/vm2/pageManager.C index e93622f120..826d7905ee 100644 --- a/src/kernel/vm2/pageManager.C +++ b/src/kernel/vm2/pageManager.C @@ -34,7 +34,7 @@ page *pageManager::getPage(void) { page *ret=NULL; //printf ("pageManager::getPage: Checking clean\n"); - printf ("pageManager::getPage:cleanCount = %d\n", clean.nodeCount); + //printf ("pageManager::getPage:cleanCount = %d\n", clean.nodeCount); if (clean.count()) { //printf ("pageManager::getPage:locking clean\n"); @@ -62,7 +62,7 @@ page *pageManager::getPage(void) inUse.add(ret); release_sem(inUseLock); } - printf ("pageManager::getPage:leaving with page = %x\n", ret); + //printf ("pageManager::getPage:leaving with page = %x\n", ret); return ret; } @@ -82,7 +82,7 @@ void pageManager::cleaner(void) { if (unused.count()) { - printf ("pageManager::cleaner: About to vacuum a page\n"); + //printf ("pageManager::cleaner: About to vacuum a page\n"); acquire_sem(unusedLock); page *first=(page *)unused.next(); first->zero(); diff --git a/src/kernel/vm2/swapFileManager.C b/src/kernel/vm2/swapFileManager.C index b69abe1867..8f9c119579 100644 --- a/src/kernel/vm2/swapFileManager.C +++ b/src/kernel/vm2/swapFileManager.C @@ -8,9 +8,10 @@ swapFileManager::swapFileManager(void) swapFile = open("/boot/var/tmp/OBOS_swap",O_RDWR|O_CREAT,0x777 ); if (swapFile==-1) printf ("swapfileManager::swapFileManger: swapfile not opened, errno = %ul, %s\n",errno,strerror(errno)); + lockFreeList=create_sem(1,"SwapFile Free List Semaphore"); // Should have team name in it. } -void swapFileManager::write_block(vnode node,void *loc,unsigned long size) +void swapFileManager::write_block(vnode &node,void *loc,unsigned long size) { printf ("swapFileManager::write_block: writing, node.fd = %d, node.offset = %d\n",node.fd, node.offset); lseek(node.fd,SEEK_SET,node.offset); @@ -18,7 +19,7 @@ void swapFileManager::write_block(vnode node,void *loc,unsigned long size) node.valid=true; } -void swapFileManager::read_block(vnode node,void *loc,unsigned long size) +void swapFileManager::read_block(vnode &node,void *loc,unsigned long size) { lseek(node.fd,SEEK_SET,node.offset); if (node.valid==false) @@ -27,18 +28,36 @@ void swapFileManager::read_block(vnode node,void *loc,unsigned long size) read(node.fd,loc,size); } -vnode swapFileManager::findNode(void) +vnode &swapFileManager::findNode(void) { - printf ("swapFileManager::findNode: 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... :-( - tmp.valid=false; - return tmp; + //printf ("swapFileManager::findNode: Entering findNode \n"); + //swapFileFreeList.dump(); + //printf ("swapFileManager::findNode: Finding a new node for you, Master: "); + vnode *newNode; + Lock(); + if (newNode=reinterpret_cast(swapFileFreeList.next())) + { + //printf (" Reused: %d\n",newNode->offset); + } + else + { + newNode=new vnode; + newNode->fd=swapFile; + newNode->offset=maxNode+=PAGE_SIZE; + newNode->valid=false; + //printf (" New One: %d\n",newNode->offset); + } + Unlock(); + //printf ("swapFileManager::findNode: swapFileFreeList is now: "); + //swapFileFreeList.dump(); + return *newNode; } -void swapFileManager::freeVNode(vnode v) +void swapFileManager::freeVNode(vnode &v) { - printf ("swapFileManager::freeNode: Freeing a new node for you, Master\n"); - // Should put this one on the free list, someday + Lock(); + //printf ("swapFileManager::freeNode: Starting Freeing a new node for you, Master: offset:%d\n",v.offset); + v.valid=false; + swapFileFreeList.add(&v); + Unlock(); } diff --git a/src/kernel/vm2/swapFileManager.h b/src/kernel/vm2/swapFileManager.h index 2fb868c5cf..e70ea8178e 100644 --- a/src/kernel/vm2/swapFileManager.h +++ b/src/kernel/vm2/swapFileManager.h @@ -1,15 +1,21 @@ #include #include #include "vm.h" +#include "OS.h" class swapFileManager { - public: - swapFileManager (void); - vnode findNode(void); // Get an unused node - void freeVNode(vnode); // Free a node - void write_block(vnode node,void *loc,unsigned long size); - void read_block(vnode node,void *loc,unsigned long size); private: int swapFile; unsigned long maxNode; + list swapFileFreeList; + sem_id lockFreeList; + + public: + swapFileManager (void); + vnode &findNode(void); // Get an unused node + void freeVNode(vnode &); // Free a node + void write_block(vnode &node,void *loc,unsigned long size); + void read_block(vnode &node,void *loc,unsigned long size); + void Lock() {acquire_sem(lockFreeList);} + void Unlock() {release_sem(lockFreeList);} }; diff --git a/src/kernel/vm2/vm.h b/src/kernel/vm2/vm.h index 1fe699d3e3..1d4b9af0b7 100644 --- a/src/kernel/vm2/vm.h +++ b/src/kernel/vm2/vm.h @@ -1,8 +1,9 @@ +#include "list.h" + #ifndef _VM_TYPES #define _VM_TYPES - const int PAGE_SIZE = 4096; -struct vnode +struct vnode : public node { int fd; unsigned long offset; diff --git a/src/kernel/vm2/vmInterface.C b/src/kernel/vm2/vmInterface.C index 94c799e937..e5d68865a3 100644 --- a/src/kernel/vm2/vmInterface.C +++ b/src/kernel/vm2/vmInterface.C @@ -76,18 +76,18 @@ int vmInterface::createArea(char *AreaName,int pageCount,void **address, address void vmInterface::freeArea(int Area) { - printf ("vmInterface::freeArea: begin\n"); + //printf ("vmInterface::freeArea: begin\n"); area *oldArea=getAM()->findArea(Area); - printf ("vmInterface::freeArea: found area %x\n",oldArea); + //printf ("vmInterface::freeArea: found area %x\n",oldArea); if (oldArea) { - printf ("vmInterface::freeArea: removing area %x from linked list\n",oldArea); + //printf ("vmInterface::freeArea: removing area %x from linked list\n",oldArea); areaManager *foo=getAM(); - printf ("vmInterface::freeArea: areaManager = %x \n",foo); + //printf ("vmInterface::freeArea: areaManager = %x \n",foo); foo->removeArea(oldArea); - printf ("vmInterface::freeArea: deleting area %x \n",oldArea); + //printf ("vmInterface::freeArea: deleting area %x \n",oldArea); oldArea->freeArea(); - printf ("vmInterface::freeArea: freeArea complete \n"); + //printf ("vmInterface::freeArea: freeArea complete \n"); delete oldArea; } else diff --git a/src/kernel/vm2/vpage.C b/src/kernel/vm2/vpage.C index d78894e06d..33ac928fd5 100644 --- a/src/kernel/vm2/vpage.C +++ b/src/kernel/vm2/vpage.C @@ -6,33 +6,30 @@ 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... { - vnode node; - node.fd=0; - node.offset=0; - return new vpage(address,node,physPage,(protection==readable)?protection:copyOnWrite,LAZY); // Not sure if LAZY is right or not + return new vpage(address,NULL,physPage,(protection==readable)?protection:copyOnWrite,LAZY); // Not sure if LAZY is right or not } // backing and/or physMem can be NULL/0. -vpage::vpage(unsigned long start,vnode backing, page *physMem,protectType prot,pageState state) +vpage::vpage(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state) { start_address=start; end_address=start+PAGE_SIZE-1; protection=prot; swappable=(state==NO_LOCK); - if (backing.fd==0) - backingNode=swapMan.findNode(); - else + if (backing) backingNode=backing; + else + backingNode=&(swapMan.findNode()); if (!physPage && (state!=LAZY) && (state!=NO_LOCK)) physPage=pageMan.getPage(); else @@ -43,8 +40,8 @@ vpage::~vpage(void) { if (physPage) // I doubt that this is always true. Probably need to check for sharing... pageMan.freePage(physPage); - if (backingNode.fd) - swapMan.freeVNode(backingNode); + if (backingNode->fd) + swapMan.freeVNode(*backingNode); } void vpage::setProtection(protectType prot) @@ -67,7 +64,7 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa 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; diff --git a/src/kernel/vm2/vpage.h b/src/kernel/vm2/vpage.h index 4ca165fbb2..9ee6a55414 100644 --- a/src/kernel/vm2/vpage.h +++ b/src/kernel/vm2/vpage.h @@ -6,7 +6,7 @@ class vpage : public node { private: page *physPage; - vnode backingNode; + vnode *backingNode; protectType protection; bool dirty; bool swappable; @@ -20,7 +20,7 @@ class vpage : public node 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(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;}