Added pooling, removing new and delete in most cases.

pageManager still needs special treatment.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@890 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Phipps
2002-08-26 20:14:54 +00:00
parent 3e5d9213bd
commit afea942ffa
15 changed files with 308 additions and 54 deletions
+1 -6
View File
@@ -1,9 +1,4 @@
SubDir OBOS_TOP src kernel vm2 ;
C++FLAGS += -g ;
CCFLAGS += -g ;
Server vmTest : area.C areaManager.C cacheManager.C page.C pageManager.C swapFileManager.C test.C vmInterface.C vpage.C ;
LinkSharedOSLibs vmTest : root be ;
BinCommand vmTest : area.C areaManager.C cacheManager.C page.C pageManager.C swapFileManager.C test.C vmInterface.C vpage.C : root be ;
+7 -7
View File
@@ -1,16 +1,16 @@
1) Need to make the paging daemon load the pages in, using semaphores.
2) See how unresolvable page faults and permissions errors are handled - need to properly handle
3) Implment cloneArea
4) Tests are not done.
3) Tests are not done.
Test:
getAreaInfo
getNextAreaInfo
cloneArea
resizeArea
setAreaProtection
mmap
mmap / munmap
paging
disk caching
5) Improve locking (remains to be seen - works ok so far)
6) I use new and delete. I know that doesn't work in kernel land. Not too tough to change, though.
7) There is no arch-level integration. This is to be tested (to death) in user land first. * == can not be done in user land.
4) Improve locking (remains to be seen - works ok so far)
5) I use new and delete. I know that doesn't work in kernel land. Not too tough to change, though.
- Pooling is now used for everything but pages
6) There is no arch-level integration. This is to be tested (to death) in user land first. * == can not be done in user land.
+32 -16
View File
@@ -1,8 +1,17 @@
#include "area.h"
#include "areaManager.h"
#include "vpage.h"
#include "vpagePool.h"
#include "vnodePool.h"
area::area (areaManager *myManager)
extern poolvpage vpagePool;
extern poolvnode vnodePool;
area::area(void)
{
}
void area::setup (areaManager *myManager)
{
manager=myManager;
}
@@ -43,11 +52,12 @@ status_t area::createAreaMappingFile(char *inName, int pageCount,void **address,
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
for (int i=0;i<pageCount;i++)
{
vnode *newVnode=new vnode;
vnode *newVnode=vnodePool.get();
newVnode->fd=fd;
newVnode->offset=offset+PAGE_SIZE*i;
newVnode->valid=true;
newPage = new vpage(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
newPage=vpagePool.get();
newPage->setup(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
vpages.add(newPage);
// printf ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset);
}
@@ -76,7 +86,8 @@ status_t area::createArea(char *inName, int pageCount,void **address, addressSpe
for (int i=0;i<pageCount;i++)
{
//printf ("in area::createArea: creating page = %d\n",i);
newPage = new vpage(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
newPage=vpagePool.get();
newPage->setup(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
vpages.add(newPage);
}
manager->unlock();
@@ -107,7 +118,8 @@ status_t area::cloneArea(area *origArea, char *inName, void **address, addressSp
{
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);
newPage=vpagePool.get();
newPage->setup(base,page->getBacking(),page->getPhysPage(),protect,inState);
vpages.add(newPage);
base+=PAGE_SIZE;
cur=cur->next;
@@ -124,23 +136,25 @@ status_t area::cloneArea(area *origArea, char *inName, void **address, addressSp
void area::freeArea(void)
{
//printf ("area::freeArea: starting \n");
//printf ("area::freeArea: starting \n");
manager->lock();
// vpages.dump();
for (struct node *cur=vpages.rock;cur;)
node *cur;
while (cur=vpages.next())
{
//printf ("area::freeArea: wasting a page: %x\n",cur);
vpage *page=(vpage *)cur;
//printf ("area::freeArea: wasting a page: %x\n",cur);
vpage *page=reinterpret_cast<vpage *>(cur);
if (finalWrite)
page->flush();
//printf ("area::freeArea: flushed a page \n");
cur=cur->next;
delete page; // Probably need to add a destructor
//printf ("area::freeArea: flushed a page \n");
page->cleanup();
//page->next=NULL;
vpagePool.put(page);
}
//printf ("area::freeArea: unlocking \n");
//printf ("area::freeArea: unlocking \n");
manager->unlock();
//printf ("area::freeArea: ending \n");
//printf ("area::freeArea: ending \n");
}
status_t area::getInfo(area_info *dest)
@@ -188,7 +202,8 @@ status_t area::resize(size_t newSize)
vpage *newPage;
for (int i=0;i<pageCount;i++)
{
newPage = new vpage(end_address+PAGE_SIZE*i-1,NULL,NULL,protection,state);
newPage=vpagePool.get();
newPage->setup(end_address+PAGE_SIZE*i-1,NULL,NULL,protection,state);
vpages.add(newPage);
}
end_address+=start_address+newSize;
@@ -203,7 +218,8 @@ status_t area::resize(size_t newSize)
{
for (cur=vpages.rock;cur->next;cur=cur->next); // INTENTIONAL - find the last one;
vpage *oldPage=(vpage *)cur;
delete oldPage;
oldPage->cleanup();
vpagePool.put(oldPage);
}
}
manager->unlock();
+2 -1
View File
@@ -24,7 +24,8 @@ class area : public node
unsigned long end_address;
vpage *findVPage(unsigned long);
public:
area(areaManager *myManager);
area(void);
void setup(areaManager *myManager);
bool nameMatch(char *matchName) {return (strcmp(matchName,name)==0);}
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);
+51
View File
@@ -0,0 +1,51 @@
#include "pageManager.h"
extern pageManager pageMan;
class poolarea
{
private:
list unused;
sem_id inUse;
public:
poolarea(void)
{
inUse = create_sem(1,"areapool");
}
area *get(void)
{
area *ret=NULL;
if (unused.count())
{
//printf ("poolarea::get: Getting an unused one!\n");
acquire_sem(inUse);
ret=(area *)unused.next();
release_sem(inUse);
}
if (ret)
{
//printf ("poolarea::get: Returning address:%x \n",ret);
return ret;
}
else
{
//printf ("poolarea::get: Getting a new page!\n");
page *newPage=pageMan.getPage();
if (!newPage)
throw ("Out of pages to allocate a pool!");
int newCount=PAGE_SIZE/sizeof(area);
acquire_sem(inUse);
//printf ("poolarea::get: Adding %d new elements to the pool!\n",newCount);
for (int i=0;i<newCount;i++)
unused.add(((void *)(newPage->getAddress()+(i*sizeof(area)))));
release_sem(inUse);
return (get()); // A little cheat - call self again to get the first one from stack...
}
}
void put(area *in)
{
acquire_sem(inUse);
unused.add(in);
release_sem(inUse);
}
};
+6 -2
View File
@@ -1,6 +1,9 @@
#include <cacheManager.h>
#include <vpagePool.h>
cacheManager::cacheManager(void) : area (NULL)
extern poolvpage vpagePool;
cacheManager::cacheManager(void) : area ()
{
myLock=create_sem(1,"Area Manager Semaphore"); // Should have team name in it.
}
@@ -33,7 +36,8 @@ 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 = vpagePool.get();
newPage->setup(begin,target,NULL,((readOnly)?readable:writable),NO_LOCK);
vpages.add(newPage);
cacheMembers.add(newPage);
unlock();
+55
View File
@@ -0,0 +1,55 @@
#include "pageManager.h"
extern pageManager pageMan;
/* This is the template
* replace TYPE with the type you need a pool for
*
class poolTYPE
{
private:
list unused;
sem_id inUse;
public:
poolTYPE(void)
{
inUse = create_sem(1,"TYPEpool");
}
TYPE *get(void)
{
TYPE *ret=NULL;
if (unused.count())
{
printf ("poolTYPE::get: Getting an unused one!\n");
acquire_sem(inUse);
ret=(TYPE *)unused.next();
release_sem(inUse);
}
if (ret)
{
printf ("poolTYPE::get: Returning address:%x \n",ret);
return ret;
}
else
{
printf ("poolTYPE::get: Getting a new page!\n");
page *newPage=pageMan.getPage();
if (!newPage)
throw ("Out of pages to allocate a pool!");
int newCount=PAGE_SIZE/sizeof(TYPE);
acquire_sem(inUse);
printf ("poolTYPE::get: Adding %d new elements to the pool!\n",newCount);
for (int i=0;i<newCount;i++)
unused.add(((void *)(newPage->getAddress()+(i*sizeof(TYPE)))));
release_sem(inUse);
return (get()); // A little cheat - call self again to get the first one from stack...
}
}
void put(TYPE *in)
{
acquire_sem(inUse);
unused.add(in);
release_sem(inUse);
}
};
*/
+4 -1
View File
@@ -2,6 +2,9 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <vnodePool.h>
extern poolvnode vnodePool;
swapFileManager::swapFileManager(void)
{
@@ -44,7 +47,7 @@ vnode &swapFileManager::findNode(void)
Unlock();
if (!newNode)
{
newNode=new vnode;
newNode=vnodePool.get();
newNode->fd=swapFile;
newNode->offset=maxNode+=PAGE_SIZE;
//printf (" New One: %d\n",newNode->offset);
+3
View File
@@ -1,3 +1,5 @@
#ifndef _SWAPFILE_MANAGER
#define _SWAPFILE_MANAGER
#include <unistd.h>
#include <fcntl.h>
#include "vm.h"
@@ -19,3 +21,4 @@ class swapFileManager {
void Lock() {acquire_sem(lockFreeList);}
void Unlock() {release_sem(lockFreeList);}
};
#endif
+2 -2
View File
@@ -94,8 +94,6 @@ int32 getInfoTest(void *parameters)
int32 mmapTest (void *parameters)
{
void *map;
loopTestParameters *params=((loopTestParameters *)parameters);
int size=params->areaSize; // Note that this is in bytes, not in pages
while (1)
@@ -109,9 +107,11 @@ int32 mmapTest (void *parameters)
printf ("mmap address = %x\n",map);
for (int i=0;i<size;i++)
writeByte((int32)map,i,i%256);
printf ("mmapTest: writing done\n");
for (int i=0;i<size;i++)
if (i%256!=readByte((int32)map,i))
printf ("ERROR! Byte at offset %d does not match: expected: %d, found: %d\n",i,i%256,readByte((int32)map,i));
printf ("mmapTest: reading done\n");
snooze(params->loopSnooze);
vm.munmap(map,size);
close(fd);
+21 -12
View File
@@ -2,10 +2,16 @@
//#include "areaManager.h"
#include "mman.h"
#include "area.h"
#include "areaPool.h"
#include "vpagePool.h"
#include "vnodePool.h"
areaManager am;
swapFileManager swapMan;
pageManager pageMan(10); // Obviously this hard coded number is a hack...
poolarea areaPool;
poolvpage vpagePool;
poolvnode vnodePool;
pageManager pageMan(30); // Obviously this hard coded number is a hack...
areaManager *vmInterface::getAM(void)
{
@@ -79,7 +85,8 @@ status_t vmInterface::resizeArea(int Area,size_t size)
int vmInterface::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect)
{
area *newArea = new area(getAM());
area *newArea = areaPool.get();
newArea->setup(getAM());
newArea->createArea(AreaName,pageCount,address,addType,state,protect);
newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE
getAM()->addArea(newArea);
@@ -93,14 +100,14 @@ void vmInterface::freeArea(int Area)
//printf ("vmInterface::freeArea: found area %x\n",oldArea);
if (oldArea)
{
//printf ("vmInterface::freeArea: removing area %x from linked list\n",oldArea);
areaManager *foo=getAM();
//printf ("vmInterface::freeArea: areaManager = %x \n",foo);
foo->removeArea(oldArea);
//printf ("vmInterface::freeArea: deleting area %x \n",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");
delete oldArea;
// printf ("vmInterface::freeArea: freeArea complete \n");
areaPool.put(oldArea);
}
else
printf ("vmInterface::freeArea: unable to find requested area\n");
@@ -132,8 +139,9 @@ int vmInterface::getAreaByName(char *name)
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);
area *newArea = areaPool.get();
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);
@@ -182,7 +190,8 @@ void *vmInterface::mmap(void *addr, size_t len, int prot, int flags, int fd, off
return addr;
}
area *newArea = new area(getAM());
area *newArea = areaPool.get();
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
+51
View File
@@ -0,0 +1,51 @@
#include "pageManager.h"
extern pageManager pageMan;
class poolvnode
{
private:
list unused;
sem_id inUse;
public:
poolvnode(void)
{
inUse = create_sem(1,"vnodepool");
}
vnode *get(void)
{
vnode *ret=NULL;
if (unused.count())
{
//printf ("poolvnode::get: Getting an unused one!\n");
acquire_sem(inUse);
ret=(vnode *)unused.next();
release_sem(inUse);
}
if (ret)
{
//printf ("poolvnode::get: Returning address:%x \n",ret);
return ret;
}
else
{
//printf ("poolvnode::get: Getting a new page!\n");
page *newPage=pageMan.getPage();
if (!newPage)
throw ("Out of pages to allocate a pool!");
int newCount=PAGE_SIZE/sizeof(vnode);
acquire_sem(inUse);
//printf ("poolvnode::get: Adding %d new elements to the pool!\n",newCount);
for (int i=0;i<newCount;i++)
unused.add(((void *)(newPage->getAddress()+(i*sizeof(vnode)))));
release_sem(inUse);
return (get()); // A little cheat - call self again to get the first one from stack...
}
}
void put(vnode *in)
{
acquire_sem(inUse);
unused.add(in);
release_sem(inUse);
}
};
+15 -5
View File
@@ -1,7 +1,9 @@
#include "vpage.h"
#include "vnodePool.h"
extern swapFileManager swapMan;
extern pageManager pageMan;
extern poolvnode vnodePool;
void vpage::flush(void)
{
@@ -14,8 +16,12 @@ void vpage::refresh(void)
swapMan.read_block(*backingNode,((void *)(physPage->getAddress())), PAGE_SIZE);
}
vpage::vpage(void)
{
}
// backing and/or physMem can be NULL/0.
vpage::vpage(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state)
void vpage::setup(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;
@@ -42,12 +48,16 @@ vpage::vpage(unsigned long start,vnode *backing, page *physMem,protectType prot,
//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)
void vpage::cleanup(void)
{
if (physPage) // Note that free means release one reference
pageMan.freePage(physPage);
if (backingNode->fd)
swapMan.freeVNode(*backingNode);
if (backingNode)
{
if (backingNode->fd)
swapMan.freeVNode(*backingNode);
vnodePool.put(backingNode);
}
}
void vpage::setProtection(protectType prot)
@@ -130,7 +140,7 @@ void vpage::setInt(unsigned long address,int value)
void vpage::pager(int desperation)
{
printf ("vpage::pager start desperation = %d\n",desperation);
//printf ("vpage::pager start desperation = %d\n",desperation);
if (!swappable)
return;
printf ("vpage::pager swappable\n");
+6 -2
View File
@@ -1,3 +1,5 @@
#ifndef VPAGE_H
#define VPAGE_H
#include <vm.h>
#include <pageManager.h>
#include <swapFileManager.h>
@@ -17,8 +19,9 @@ 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(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state); // backing and/or physMem can be NULL/0.
~vpage(void);
vpage(void);
void setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state); // backing and/or physMem can be NULL/0.
void cleanup(void);
void setProtection(protectType prot);
protectType getProtection(void) {return protection;}
void *getStartAddress(void) {return (void *)start_address;}
@@ -43,3 +46,4 @@ class vpage : public node
int getInt(unsigned long offset); // This is for testing only
void setInt(unsigned long offset,int value); // This is for testing only
};
#endif
+52
View File
@@ -0,0 +1,52 @@
#include "pageManager.h"
#include "vpage.h"
extern pageManager pageMan;
class poolvpage
{
private:
list unused;
sem_id inUse;
public:
poolvpage(void)
{
inUse = create_sem(1,"vpagepool");
}
vpage *get(void)
{
vpage *ret=NULL;
if (unused.count())
{
//printf ("poolvpage::get: Getting an unused one!\n");
acquire_sem(inUse);
ret=(vpage *)unused.next();
release_sem(inUse);
}
if (ret)
{
//printf ("poolvpage::get: Returning address:%x \n",ret);
return ret;
}
else
{
//printf ("poolvpage::get: Getting a new page!\n");
page *newPage=pageMan.getPage();
if (!newPage)
throw ("Out of pages to allocate a pool!");
int newCount=PAGE_SIZE/sizeof(vpage);
acquire_sem(inUse);
//printf ("poolvpage::get: Adding %d new elements to the pool!\n",newCount);
for (int i=0;i<newCount;i++)
unused.add(((void *)(newPage->getAddress()+(i*sizeof(vpage)))));
release_sem(inUse);
return (get()); // A little cheat - call self again to get the first one from stack...
}
}
void put(vpage *in)
{
acquire_sem(inUse);
unused.add(in);
release_sem(inUse);
}
};