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
This commit is contained in:
parent
5b87d86af3
commit
7bebb1dec3
@ -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;i<pageCount;i++)
|
||||
{
|
||||
newVnode.fd=fd;
|
||||
newVnode.offset=offset+PAGE_SIZE*i;
|
||||
newVnode->fd=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;i<pageCount;i++)
|
||||
{
|
||||
printf ("in area::createArea: creating page = %d\n",i);
|
||||
newPage = new vpage(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
|
||||
//printf ("in area::createArea: creating page = %d\n",i);
|
||||
newPage = new vpage(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
|
||||
vpages.add(newPage);
|
||||
}
|
||||
state=inState;
|
||||
@ -74,15 +71,15 @@ status_t area::createArea(char *name, int pageCount,void **address, addressSpec
|
||||
end_address=base+pageCount*PAGE_SIZE;
|
||||
manager->unlock();
|
||||
*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<pageCount;i++)
|
||||
{
|
||||
newPage = new vpage(end_address+PAGE_SIZE*i-1,newVnode,NULL,protection,state);
|
||||
newPage = new vpage(end_address+PAGE_SIZE*i-1,NULL,NULL,protection,state);
|
||||
vpages.add(newPage);
|
||||
}
|
||||
end_address+=start_address+newSize;
|
||||
|
@ -33,7 +33,7 @@ void *cacheManager::createBlock(vnode *target,bool readOnly)
|
||||
}
|
||||
lock();
|
||||
// Create a vnode here
|
||||
vpage *newPage = new vpage(begin,*target,NULL,((readOnly)?readable:writable),NO_LOCK);
|
||||
vpage *newPage = new vpage(begin,target,NULL,((readOnly)?readable:writable),NO_LOCK);
|
||||
vpages.add(newPage);
|
||||
cacheMembers.add(newPage);
|
||||
unlock();
|
||||
|
@ -14,20 +14,34 @@ class list {
|
||||
list(void) {nodeCount=0;rock=NULL;}
|
||||
void add (void *in)
|
||||
{
|
||||
struct node *newNode=(node *)in;
|
||||
struct node *newNode=reinterpret_cast<node *>(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();
|
||||
//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();
|
||||
//dump();
|
||||
}
|
||||
void dump(void)
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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<vnode *>(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();
|
||||
}
|
||||
|
@ -1,15 +1,21 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#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);}
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;}
|
||||
|
Loading…
Reference in New Issue
Block a user