Another checkpoint. Big one, this time.

Changed the whole way locking was done. What was I thinking?
Many changes and cleanup ideas from Ingo (thanks!).
Not perfect yet, but much better. Still a few things left to implement
in the COW arena - mmap doesn't use it. Also need to finish the vpageManager
which will cause mmap and cacheManager to use the same vnodes where possible.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1042 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Phipps
2002-09-14 17:03:16 +00:00
parent 7eb88330cf
commit 5fb6c38b6e
24 changed files with 611 additions and 214 deletions
+38 -38
View File
@@ -15,8 +15,9 @@ area::area(void)
void area::setup (areaManager *myManager)
{
printf ("area::setup setting up new area\n");
//printf ("area::setup setting up new area\n");
manager=myManager;
//printf ("area::setup done setting up new area\n");
}
unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount)
@@ -28,7 +29,7 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque
case EXACT:
base=manager->getNextAddress(pageCount,requested);
if (base!=requested)
return B_ERROR;
return 0;
break;
case BASE:
base=manager->getNextAddress(pageCount,requested);
@@ -40,6 +41,8 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque
base=manager->getNextAddress(pageCount,KERNEL_BASE);
break;
case CLONE: base=0;break; // Not sure what to do...
default: // should never happen
throw ("Unknown type passed to mapAddressSpecToAddress");
}
// 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;
@@ -51,8 +54,9 @@ status_t area::createAreaMappingFile(char *inName, int pageCount,void **address,
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
vpage *newPage;
manager->lock();
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
if (base==0)
return B_ERROR;
for (int i=0;i<pageCount;i++)
{
vnode *newVnode=new (vmBlock->vnodePool->get()) vnode;
@@ -64,13 +68,13 @@ status_t area::createAreaMappingFile(char *inName, int pageCount,void **address,
vpages.add(newPage);
// printf ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset);
}
manager->unlock();
state=inState;
start_address=base;
end_address=base+pageCount*PAGE_SIZE;
end_address=base+(pageCount*PAGE_SIZE)-1;
*address=(void *)base;
finalWrite=true;
return B_OK;
}
status_t area::createArea(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect)
@@ -82,22 +86,23 @@ status_t area::createArea(char *inName, int pageCount,void **address, addressSpe
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");
// printf ("area::createArea: Locked in createArea\n");
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
printf ("area::createArea: base address = %d\n",base);
if (base==0)
return B_ERROR;
// printf ("area::createArea: base address = %ld\n",base);
for (int i=0;i<pageCount;i++)
{
printf ("in area::createArea: creating page = %d\n",i);
//printf ("in area::createArea: creating page = %d\n",i);
newPage=new (vmBlock->vpagePool->get()) vpage;
newPage->setup(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
vpages.add(newPage);
}
manager->unlock();
start_address=base;
end_address=base+pageCount*PAGE_SIZE;
end_address=base+(pageCount*PAGE_SIZE)-1;
*address=(void *)base;
printf ("area::createArea: unlocked in createArea\n");
// printf ("area::createArea: unlocked in createArea\n");
return B_OK;
}
status_t area::cloneArea(area *origArea, char *inName, void **address, addressSpec type,pageState inState,protectType protect)
@@ -105,18 +110,14 @@ status_t area::cloneArea(area *origArea, char *inName, void **address, addressSp
// 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);
if (base==0)
return B_ERROR;
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;
@@ -127,24 +128,21 @@ status_t area::cloneArea(area *origArea, char *inName, void **address, addressSp
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();
end_address=base+(pageCount*PAGE_SIZE)-1;
*address=(void *)start_address;
finalWrite=false;
// printf ("area::cloneArea: unlocked\n");
return B_OK;
}
void area::freeArea(void)
{
//printf ("area::freeArea: starting \n");
manager->lock();
// vpages.dump();
node *cur;
while (cur=vpages.next())
while ((cur=vpages.next())!=NULL)
{
//printf ("area::freeArea: wasting a page: %x\n",cur);
vpage *page=reinterpret_cast<vpage *>(cur);
@@ -156,16 +154,16 @@ void area::freeArea(void)
vmBlock->vpagePool->put(page);
}
//printf ("area::freeArea: unlocking \n");
manager->unlock();
//printf ("area::freeArea: ending \n");
}
status_t area::getInfo(area_info *dest)
{
// no need to lock here...
dest->area=areaID;
strcpy(dest->name,name);
dest->size=end_address-start_address;
dest->lock=state;
dest->protection=protection;
dest->team=manager->getTeam();
dest->ram_size=0;
dest->in_count=0;
@@ -190,7 +188,7 @@ bool area::contains(void *address)
unsigned long base=(unsigned long)(address);
// printf ("area::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));
return ((start_address<=base) && (base<=end_address));
}
status_t area::resize(size_t newSize)
@@ -200,7 +198,6 @@ status_t area::resize(size_t newSize)
return B_OK;
if (newSize>oldSize)
{
manager->lock();
int pageCount = (newSize-oldSize) / PAGE_SIZE;
vpage *newPage;
for (int i=0;i<pageCount;i++)
@@ -213,31 +210,30 @@ status_t area::resize(size_t newSize)
}
else
{
manager->lock();
int pageCount = (oldSize -newSize) / PAGE_SIZE;
vpage *oldPage;
struct node *cur;
for (int i=0;i<pageCount;i++) // This is probably really slow. Adding an "end" to list would be faster.
{
for (cur=vpages.rock;cur->next;cur=cur->next); // INTENTIONAL - find the last one;
vpage *oldPage=(vpage *)cur;
oldPage=(vpage *)cur;
vpages.remove(cur);
oldPage->cleanup();
vmBlock->vpagePool->put(oldPage);
}
}
manager->unlock();
return B_OK;
}
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();
return B_OK;
}
vpage *area::findVPage(unsigned long address)
@@ -246,6 +242,8 @@ vpage *area::findVPage(unsigned long address)
for (struct node *cur=vpages.rock;cur;cur=cur->next)
{
vpage *page=(vpage *)cur;
//printf ("Examining following vpage, looking for address %lx\n",address);
//page->dump();
if (page->contains(address))
return page;
}
@@ -267,7 +265,7 @@ 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);
return page->getByte(address,manager);
else
return 0;
}
@@ -277,7 +275,7 @@ 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);
page->setByte(address,value,manager);
}
int area::getInt(unsigned long address) // This is for testing only
@@ -285,7 +283,9 @@ 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);
return page->getInt(address,manager);
else
return 0;
}
void area::setInt(unsigned long address,int value) // This is for testing only
@@ -293,7 +293,7 @@ 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);
page->setInt(address,value,manager);
}
void area::pager(int desperation)
@@ -318,7 +318,7 @@ 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);
printf ("area::dump: size = %ld, lock = %d, address = %lx\n",end_address-start_address,state,start_address);
for (struct node *cur=vpages.rock;cur;)
{
vpage *page=(vpage *)cur;
+166 -21
View File
@@ -1,14 +1,26 @@
#include <new.h>
#include "mman.h"
#include "areaManager.h"
#include "vmHeaderBlock.h"
#include "areaPool.h"
extern vmHeaderBlock *vmBlock;
bool areaIsLessThan(void *a,void *b)
{
return (((reinterpret_cast<area *>(a))->getStartAddress()) < (reinterpret_cast<area *>(b))->getStartAddress());
}
areaManager::areaManager(void)
{
team=0; // should be proc_get_current_proc_id()
myLock=0;
myLock=create_sem(1,"Area Manager Semaphore"); // Should have team name in it.
areas.setIsLessThan(areaIsLessThan);
}
unsigned long areaManager::getNextAddress(int pages, unsigned long start)
{
// This function needs to deal with the possibility that we run out of address space...
// areas.dump();
unsigned long end=start+(pages*PAGE_SIZE)-1;
for (struct node *cur=areas.rock;cur;cur=cur->next)
@@ -27,19 +39,54 @@ unsigned long areaManager::getNextAddress(int pages, unsigned long start)
return start;
}
void areaManager::freeArea(int areaID)
{
printf ("areaManager::freeArea: begin\n");
lock();
area *oldArea=findArea(areaID);
//printf ("areaManager::freeArea: found area %x\n",oldArea);
if (oldArea)
{
// printf ("areaManager::freeArea: removing area %x from linked list\n",oldArea);
// printf ("areaManager::freeArea: areaManager = %x \n",manager);
removeArea(oldArea);
// printf ("areaManager::freeArea: deleting area %x \n",oldArea);
oldArea->freeArea();
// printf ("areaManager::freeArea: freeArea complete \n");
vmBlock->areaPool->put(oldArea);
}
else
printf ("areaManager::freeArea: unable to find requested area\n");
unlock();
}
area *areaManager::findAreaLock(void *address)
{
lock();
area *retVal=findArea(address);
unlock();
return retVal;
}
area *areaManager::findArea(char *address)
{
for (struct node *cur=areas.rock;cur;cur=cur->next)
printf ("Finding area by string\n");
lock();
area *retVal=NULL;
for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next)
{
area *myArea=(area *)cur;
if (myArea->nameMatch(address))
return myArea;
retVal= myArea;
}
return NULL;
unlock();
return retVal;
}
area *areaManager::findArea(void *address)
{
// THIS DOES NOT HAVE LOCKING - all callers must lock.
//printf ("Finding area by void * address\n");
for (struct node *cur=areas.rock;cur;cur=cur->next)
{
area *myArea=(area *)cur;
@@ -52,73 +99,171 @@ area *areaManager::findArea(void *address)
return NULL;
}
area *areaManager::findAreaLock(area_id id)
{
printf ("Finding area by areaID \n");
lock();
area *retVal=findArea(id);
unlock();
return retVal;
}
area *areaManager::findArea(area_id id)
{
for (struct node *cur=areas.rock;cur;cur=cur->next)
//printf ("Finding area by area_id\n");
area *retVal=NULL;
for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next)
{
area *myArea=(area *)cur;
if (myArea->getAreaID()==id)
return myArea;
retVal= myArea;
}
return NULL;
return retVal;
}
bool areaManager::fault(void *fault_address, bool writeError) // true = OK, false = panic.
{
area *myArea;
if (myArea=findArea(fault_address))
return myArea->fault(fault_address,writeError);
bool retVal;
printf ("Faulting \n");
lock();
myArea=findArea(fault_address);
if (myArea)
retVal= myArea->fault(fault_address,writeError);
else
return false;
retVal= false;
unlock();
return retVal;
}
int areaManager::nextAreaID=0;
int areaManager::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect)
{
printf ("Creating an area\n");
lock();
area *newArea = new (vmBlock->areaPool->get()) area;
// printf ("areaManager::createArea - got a new area (%p) from the areaPool\n",newArea);
newArea->setup(this);
// printf ("areaManager::createArea - setup complete\n");
newArea->createArea(AreaName,pageCount,address,addType,state,protect);
// printf ("areaManager::createArea - new area's createArea called\n");
newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE
// printf ("areaManager::createArea - new area's setAreaID called\n");
addArea(newArea);
// printf ("areaManager::createArea - new area added to list\n");
int retVal=newArea->getAreaID();
// printf ("areaManager::createArea - new area id found\n");
unlock();
//printf ("Done Creating an area\n");
return retVal;
}
int areaManager::cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType,pageState state,protectType protect)
{
printf ("Cloning an area\n");
lock();
area *newArea = new (vmBlock->areaPool->get()) area;
newArea->setup(this);
area *oldArea=findArea(newAreaID);
newArea->cloneArea(oldArea,AreaName,address,addType,state,protect);
newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE
addArea(newArea);
int retVal=newArea->getAreaID();
unlock();
return retVal;
}
char areaManager::getByte(unsigned long address)
{
area *myArea;
if (myArea=findArea((void *)address))
return myArea->getByte(address);
int retVal;
myArea=findArea((void *)address);
if (myArea)
retVal=myArea->getByte(address);
else
return 0;
retVal= 0;
return retVal;
}
int areaManager::getInt(unsigned long address)
{
area *myArea;
if (myArea=findArea((void *)address))
return myArea->getInt(address);
int retVal;
myArea=findArea((void *)address);
if (myArea)
retVal=myArea->getInt(address);
else
return 0;
retVal= 0;
return retVal;
}
void areaManager::setByte(unsigned long offset,char value)
void areaManager::setByte(unsigned long address,char value)
{
area *myArea;
if (myArea=findArea((void *)offset))
myArea->setByte(offset,value);
myArea=findArea((void *)address);
if (myArea)
myArea->setByte(address,value);
}
void areaManager::setInt(unsigned long offset,int value)
void areaManager::setInt(unsigned long address,int value)
{
area *myArea;
if (myArea=findArea((void *)offset))
myArea->setInt(offset,value);
myArea=findArea((void *)address);
if (myArea)
myArea->setInt(address,value);
}
void areaManager::pager(int desperation)
{
lock();
for (struct node *cur=areas.rock;cur;cur=cur->next)
{
area *myArea=(area *)cur;
//printf ("areaManager::pager; area = \n");
//myArea->dump();
myArea->pager(desperation);
}
unlock();
}
void areaManager::saver(void)
{
lock();
for (struct node *cur=areas.rock;cur;cur=cur->next)
{
area *myArea=(area *)cur;
myArea->saver();
}
unlock();
}
void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
char name[MAXPATHLEN];
// Get the filename from fd...
strcpy( name,"mmap - need to include fileName");
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);
lock();
if (flags & MAP_ANON)
{
createArea(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr, addType ,LAZY,protType);
return addr;
}
area *newArea = new (vmBlock->areaPool->get()) area;
newArea->setup(this);
//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
addArea(newArea);
newArea->getAreaID();
//pageMan.dump();
//newArea->dump();
unlock();
return addr;
}
+91 -3
View File
@@ -1,24 +1,112 @@
#include "area.h"
#include "olist.h"
class areaManager // One of these per process
{
private:
list areas;
orderedList areas;
team_id team;
sem_id myLock;
static int nextAreaID;
public:
areaManager ();
void addArea(area *newArea) {areas.add(newArea);}
void removeArea(area *oldArea) {areas.remove(oldArea); }
void freeArea(int area);
team_id getTeam(void) {return team;}
unsigned long getNextAddress(int pages,unsigned long minimum=USER_BASE);
area *findArea(void *address);
area *findAreaLock(void *address);
area *findArea(char *address);
area *findArea(area_id id);
area *findAreaLock(area_id id);
status_t setProtection(int areaID,protectType prot)
{
status_t retVal;
lock();
area *myArea=findArea(areaID);
if (myArea)
retVal= myArea->setProtection(prot);
else
retVal= B_ERROR;
unlock();
return retVal;
}
status_t resizeArea(int Area,size_t size)
{
status_t retVal;
lock();
area *oldArea=findArea(Area);
if (oldArea)
retVal= oldArea->resize(size);
else
retVal= B_ERROR;
unlock();
return retVal;
}
status_t getAreaInfo(int areaID,area_info *dest)
{
status_t retVal;
lock();
area *oldArea=findArea(areaID);
if (oldArea)
retVal=oldArea->getInfo(dest);
else
retVal=B_ERROR;
unlock();
return retVal;
}
status_t getInfoAfter(int32 & areaID,area_info *dest)
{
status_t retVal;
lock();
area *oldArea=findArea(areaID);
if (oldArea->next)
{
area *newCurrent=(reinterpret_cast<area *>(oldArea->next));
retVal=newCurrent->getInfo(dest);
areaID=(int)newCurrent;
}
else
retVal=B_ERROR;
unlock();
return retVal;
}
int getAreaByName(char *name)
{
int retVal;
lock();
area *oldArea=findArea(name);
if (oldArea)
retVal= oldArea->getAreaID();
else
retVal= B_ERROR;
unlock();
return retVal;
}
int createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) ;
void pager(int desperation);
void saver(void);
void lock() {acquire_sem(myLock);}
void unlock() {release_sem(myLock);}
void lock()
{
static long lockCount=0;
if (!((lockCount++)%200))
printf ("locking\n");
acquire_sem(myLock);
}
void unlock() {/*printf ("unlocking\n");*/release_sem(myLock);}
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
status_t 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...
status_t retVal=B_OK;
lock();
int area=findArea(addr)->getAreaID();
if (area) freeArea(area);
unlock();
return retVal;
}
int cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType=ANY, pageState state=NO_LOCK, protectType prot=writable);
bool fault(void *fault_address, bool writeError); // true = OK, false = panic.
+1 -1
View File
@@ -31,7 +31,7 @@ area *poolarea::get(void)
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)))));
unused.add(((node *)(newPage->getAddress()+(i*sizeof(area)))));
release_sem(inUse);
return (get()); // A little cheat - call self again to get the first one from stack...
}
+1 -1
View File
@@ -15,7 +15,7 @@ class poolarea
void put(area *in)
{
acquire_sem(inUse);
unused.add(in);
unused.add((node *)in);
release_sem(inUse);
}
+12
View File
@@ -3,6 +3,17 @@
#include <vpagePool.h>
#include "vmHeaderBlock.h"
bool cacheMemberIsLessThan(void *a,void *b)
{
vnode *v1 = reinterpret_cast<cacheMember *>(a)->vn;
vnode *v2 = reinterpret_cast<cacheMember *>(b)->vn;
if (v1->fd < v2->fd)
return true;
if ((v1->fd==v2->fd) && (v1->offset<v2->offset))
return true;
return false;
}
extern vmHeaderBlock *vmBlock;
// TODO - we need to (somehow) make sure that the same vnodes here are shared with mmap.
// Maybe a vnode manager...
@@ -28,6 +39,7 @@ void *cacheManager::createBlock(vnode *target,bool readOnly)
bool foundSpot=false;
vpage *prev=NULL,*cur=NULL;
unsigned long begin=CACHE_BEGIN;
// Find a place in the cache's virtual space to put this vnode...
if (vpages.rock)
for (cur=((vpage *)(vpages.rock));!foundSpot && cur;cur=(vpage *)(cur->next))
if (cur->getStartAddress()!=(void *)begin)
+2 -1
View File
@@ -2,6 +2,7 @@
#include <vm.h>
#include <vpage.h>
#include <area.h>
#include <olist.h>
struct cacheMember : public node
{
@@ -12,7 +13,7 @@ struct cacheMember : public node
class cacheManager : public area
{
private:
list cacheMembers; // Yes, this is slow and should be a hash table. This should be done prior to
orderedList cacheMembers; // Yes, this is slow and should be a hash table. This should be done prior to
// moving into the kernel, so we can test it better.
// 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);
+3 -4
View File
@@ -11,10 +11,9 @@ struct node
class list {
public:
list(void) {nodeCount=0;rock=NULL;}
void add (void *in)
list(void){nodeCount=0;rock=NULL;}
void add (node *newNode)
{
struct node *newNode=reinterpret_cast<node *>(in);
newNode->next=rock;
rock=newNode;
nodeCount++;
@@ -60,7 +59,7 @@ class list {
{
for (struct node *cur=rock;cur;cur=cur->next)
{
printf ("list::dump: At %x, next = %x\n",cur,cur->next);
printf ("list::dump: At %p, next = %p\n",cur,cur->next);
}
}
struct node *rock;
+102
View File
@@ -0,0 +1,102 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "olist.h"
#include "OS.h"
struct iltTest : public node
{
iltTest(int i) {value=i;}
int value;
};
bool ilt(void *a,void *b)
{
iltTest *a1=reinterpret_cast<iltTest *>(a);
iltTest *b1=reinterpret_cast<iltTest *>(b);
if (a1->value<b1->value)
return true;
return false;
}
int main(int argc,char **argv)
{
// Test 1 - Try to add to foo without setting an isLessThan function
try {
orderedList foo;
node tmp;
foo.add(&tmp);
}
catch (const char *badness)
{
if (strcmp(badness,"Attempting to use an ordered list without setting up a 'toLessThan' function"))
printf ("Failure on adding with no isLessThan, error = %s\n", badness);
printf ("Success on adding with no isLessThan, \n" );
}
catch(...)
{
printf ("Failure on adding with no isLessThan, unknown exception\n");
}
orderedList foo;
foo.setIsLessThan(ilt);
printf ("Add the first couple, in order (easy)\n");
iltTest first(1);
foo.add(&first);
iltTest second(2);
foo.add(&second);
foo.dump();
printf ("Add the next three, not in order (harder)\n");
iltTest third(3);
iltTest fourth(4);
iltTest fifth(5);
foo.add(&fourth);
foo.add(&third);
foo.add(&fifth);
foo.dump();
while (iltTest *n=(iltTest *)(foo.next()))
printf ("Popped %d\n",n->value);
orderedList bar;
bar.setIsLessThan(ilt);
while (iltTest *n=(iltTest *)(bar.next()))
printf ("Popped %d\n",n->value);
for (int a=0;a<100;a++)
bar.add(new iltTest(a));
while (iltTest *n=(iltTest *)(bar.next()))
printf ("Popped %d\n",n->value);
for (int a=1000;a>=0;a--)
bar.add(new iltTest(a));
while (iltTest *n=(iltTest *)(bar.next()))
if (!(n->value%50)) printf ("Popped %d\n",n->value);
printf ("Setting up simple case\n");
foo.add(&first);
foo.dump();
printf ("Removing simple case\n");
foo.remove(&first);
foo.dump();
printf ("Setting up middle case\n");
foo.add(&first);
foo.add(&second);
foo.dump();
printf ("Removing middle case\n");
foo.remove(&second);
foo.dump();
foo.remove(&first);
printf ("Setting up final case\n");
foo.add(&first);
foo.add(&second);
foo.add(&third);
foo.dump();
printf ("Removing final case\n");
foo.remove(&second);
foo.dump();
return 0;
}
+69
View File
@@ -0,0 +1,69 @@
#ifndef _OLIST_H
#define _OLIST_H
#include "list.h"
static bool throwException (void *foo, void *bar)
{
throw ("Attempting to use an ordered list without setting up a 'toLessThan' function");
}
class orderedList : public list
{
public:
orderedList(void) {nodeCount=0;rock=NULL; isLessThan=throwException; }
void setIsLessThan (bool (*iLT)(void *,void *)) { isLessThan=iLT; }
void add(node *in)
{
nodeCount++;
//printf ("orderedList::add starting\n");
if (!rock || isLessThan(in,rock))
{ // special case - this will be the first one
//printf ("orderedList::specialCase starting\n");
in->next=rock;
rock=in;
}
else
{
//printf ("orderedList::Normal Case starting\n");
bool done=false;
for (struct node *cur=rock;cur && !done;cur=cur->next)
if (!(cur->next) || isLessThan(in,cur->next))
{ // If we have found our niche, *OR* this is the last element, insert here.
//printf ("orderedList::Normal Case Adding Start\n");
in->next=cur->next;
cur->next=in;
done=true;
//printf ("orderedList::Normal Case Adding END\n");
}
//printf ("orderedList::Normal Case ending\n");
}
}
void remove(node *toNuke)
{
if (rock==toNuke)
{
rock=rock->next;
nodeCount--;
}
else
{
bool done=false;
for (struct node *cur=rock;!done && (cur->next);cur=cur->next)
if (cur->next==toNuke)
{
cur->next=toNuke->next;
nodeCount--;
done=true;
}
else if (isLessThan(cur->next,toNuke)) // this is backwards intentionally
done=true;
}
}
private:
bool (*isLessThan)(void *a,void *b);
};
#endif
+2 -2
View File
@@ -7,11 +7,11 @@ class page : public node {
void *cpuSpecific;
void *physicalAddress;
public:
int count;
long count; // Yes, this is large. However, the only atomic add that I have in userland works on int32's. In kernel land, we could shrink this
page(void) {cpuSpecific=NULL;physicalAddress=NULL;};
void setup (void *address) {count=0;physicalAddress=address;};
void zero(void);
unsigned long getAddress(void) {return (unsigned long)physicalAddress;}
void dump(void) { printf ("Page %x, physicalAddress = %x\n",this,getAddress()); }
void dump(void) { printf ("Page %p, physicalAddress = %lx\n",this,getAddress()); }
};
#endif
+4 -5
View File
@@ -22,7 +22,7 @@ void pageManager::setup(void *area,int pages)
//printf ("newPage = %x, setup = %x\n",newPage,addOffset(area,(i+pageOverhead)*PAGE_SIZE));
//printf ("i = %d, sizeof(page) = %x, pageOverhead = %d\n",i,sizeof(page),pageOverhead);
//newPage->dump();
unused.add(addOffset(area,i*sizeof(page)));
unused.add(newPage);
}
cleanLock=create_sem (1,"clean_lock");
@@ -77,9 +77,7 @@ page *pageManager::getPage(void)
void pageManager::freePage(page *toFree)
{
// 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)
if (atomic_add(&(toFree->count),-1)==0)
{
acquire_sem(inUseLock);
inUse.remove(toFree);
@@ -88,6 +86,7 @@ void pageManager::freePage(page *toFree)
unused.add(toFree);
release_sem(unusedLock);
}
// printf (" new value = %d, page = %x\n",toFree->count,toFree->getAddress());
}
void pageManager::cleaner(void)
@@ -99,11 +98,11 @@ void pageManager::cleaner(void)
//printf ("pageManager::cleaner: About to vacuum a page\n");
acquire_sem(unusedLock);
page *first=(page *)unused.next();
release_sem(unusedLock);
first->zero();
acquire_sem(cleanLock);
clean.add(first);
release_sem(cleanLock);
release_sem(unusedLock);
//printf ("pageManager::cleaner: All done with vacuum a page\n");
snooze(125000);
}
+1 -1
View File
@@ -29,10 +29,10 @@ void swapFileManager::write_block(vnode &node,void *loc,unsigned long size)
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 into %x\n",node.fd, node.offset,loc);
lseek(node.fd,node.offset,SEEK_SET);
read(node.fd,loc,size);
}
+30 -21
View File
@@ -11,27 +11,36 @@ void writeByte(unsigned long addr,unsigned int offset, char value) { vm.setByte(
unsigned char readByte(unsigned long addr,unsigned int offset ) { char value=vm.getByte(addr+offset); return value; }
int createFillAndTest(int pages)
int createFillAndTest(int pages,char *name)
{
try{
unsigned long addr;
int area1;
printf ("createFillAndTest: about to create \n");
printf ("%s: createFillAndTest: about to create \n",name);
area1=vm.createArea("Mine",pages,(void **)(&addr));
printf ("createFillAndTest: create done\n");
printf ("%s: createFillAndTest: create done\n",name);
for (int i=0;i<pages*PAGE_SIZE;i++)
{
if (!(i%100) )
printf ("Writing to byte %d of area %s\n",i,name);
writeByte(addr,i,i%256);
printf ("createFillAndTest: writing done\n");
}
printf ("%s: createFillAndTest: writing done\n",name);
for (int i=0;i<pages*PAGE_SIZE;i++)
{
if (!(i%100) )
printf ("Reading from byte %d of area %s\n",i,name);
if (i%256!=readByte(addr,i))
printf ("ERROR! Byte at offset %d does not match: expected: %d, found: %d\n",i,i%256,readByte(addr,i));
printf ("createFillAndTest: reading done\n");
}
printf ("%s: createFillAndTest: reading done\n",name);
return area1;
}
catch (...)
{
printf ("Exception thrown!\n");
}
return 0;
}
struct loopTestParameters
@@ -53,7 +62,7 @@ int32 loopTest(void *parameters)
{
snooze(params->initialSnooze);
printf ("Creating %s area\n",params->name);
area1=createFillAndTest(params->areaSize);
area1=createFillAndTest(params->areaSize,params->name);
snooze(params->holdSnooze);
printf ("Freeing %s area\n",params->name);
vm.freeArea(area1);
@@ -71,20 +80,20 @@ int32 getInfoTest(void *parameters)
{
snooze(params->initialSnooze);
//printf ("Creating %s area\n",params->name);
area1=createFillAndTest(params->areaSize);
area1=createFillAndTest(params->areaSize,params->name);
snooze(params->holdSnooze);
vm.getAreaInfo(area1,&ai);
printf ("Area info : \n");
printf ("name : %s\n",ai.name);
printf ("size : %d\n",ai.size);
printf ("lock : %d\n",ai.lock);
printf ("team : %d\n",ai.team);
printf ("ram_size : %d\n",ai.ram_size);
printf ("in_count : %d\n",ai.in_count);
printf ("out_count : %d\n",ai.out_count);
printf ("copy_count : %d\n",ai.copy_count);
printf ("address : %x\n",ai.address);
printf ("size : %ld\n",ai.size);
printf ("lock : %ld\n",ai.lock);
printf ("team : %ld\n",ai.team);
printf ("ram_size : %ld\n",ai.ram_size);
printf ("in_count : %ld\n",ai.in_count);
printf ("out_count : %ld\n",ai.out_count);
printf ("copy_count : %ld\n",ai.copy_count);
printf ("address : %p\n",ai.address);
printf ("Freeing %s area\n",params->name);
vm.freeArea(area1);
@@ -105,7 +114,7 @@ int32 mmapTest (void *parameters)
printf ("Creating %s mmap\n",params->name);
snooze(params->holdSnooze);
map=vm.mmap(NULL,size,PROT_WRITE|PROT_READ,MAP_SHARED,fd,0);
printf ("mmap address = %x\n",map);
printf ("mmap address = %p\n",map);
for (int i=0;i<size;i++)
writeByte((int32)map,i,i%256);
printf ("mmapTest: writing done\n");
@@ -130,12 +139,12 @@ int32 cloneTest (void *parameters)
{
snooze(params->initialSnooze);
// printf ("Creating %s area, size = %d\n",params->name,params->areaSize);
area1=createFillAndTest(params->areaSize);
area1=createFillAndTest(params->areaSize,params->name);
// printf ("cloning, create done \n");
area2=vm.cloneArea(area1,"Clone1",&cloneAddr);
for (int i=0;i<params->areaSize*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 ("ERROR! Clone Byte at offset %d of %p 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);
@@ -157,9 +166,9 @@ int main(int argc,char **argv)
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));
//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(1000000000);
-1
View File
@@ -16,7 +16,6 @@ struct vnode : public node
count=0;
}
};
typedef unsigned long owningProcess;
#define B_OS_NAME_LENGTH 32
enum protectType {none=0,readable, writable,copyOnWrite,symCopyOnWrite};
enum pageState {FULL,CONTIGUOUS,LAZY,NO_LOCK,LOMEM};
+38 -89
View File
@@ -14,6 +14,8 @@
vmHeaderBlock *vmBlock;
static areaManager am;
// The purpose of this interface is to validate options, translate where necessary and pass through to the areaManager.
areaManager *getAM(void)
{
return &am;
@@ -62,7 +64,7 @@ int32 pagerThread(void *areaMan)
vmInterface::vmInterface(int pages)
{
char temp[1000];
sprintf (temp,"vm_test_clone_%d",getpid());
sprintf (temp,"vm_test_clone_%ld",getpid());
if (clone_area(temp,(void **)(&vmBlock),B_ANY_ADDRESS,B_WRITE_AREA,find_area("vm_test"))<0)
{
// This is compatability for in BeOS usage only...
@@ -97,7 +99,6 @@ vmInterface::vmInterface(int pages)
//printf ("vmBlock is at %x, end of structures is at %x, pageMan called with address %x, pages = %d\n",vmBlock,currentAddress,addToPointer(vmBlock,PAGE_SIZE*pageCount),pages-pageCount);
vmBlock->pageMan->setup(addToPointer(vmBlock,PAGE_SIZE*pageCount),pages-pageCount);
}
nextAreaID=0;
resume_thread(spawn_thread(cleanerThread,"cleanerThread",0,(vmBlock->pageMan)));
resume_thread(spawn_thread(saverThread,"saverThread",0,getAM()));
@@ -106,98 +107,68 @@ vmInterface::vmInterface(int pages)
int vmInterface::getAreaByAddress(void *address)
{
area *myArea = getAM()->findArea(address);
int retVal;
area *myArea = getAM()->findAreaLock(address);
if (myArea)
return myArea->getAreaID();
retVal= myArea->getAreaID();
else
return B_ERROR;
retVal= B_ERROR;
return retVal;
}
status_t vmInterface::setAreaProtection(int Area,protectType prot)
{
area *myArea = getAM()->findArea(Area);
if (myArea)
return myArea->setProtection(prot);
else
return B_ERROR;
status_t retVal;
retVal= getAM()->setProtection(Area,prot);
return retVal;
}
status_t vmInterface::resizeArea(int Area,size_t size)
{
area *oldArea;
oldArea=getAM()->findArea(Area);
if (oldArea)
return oldArea->resize(size);
else
return B_ERROR;
status_t retVal;
retVal = getAM()->resizeArea(Area,size);
return retVal;
}
int vmInterface::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect)
{
area *newArea = new (vmBlock->areaPool->get()) area;
areaManager *foo;
printf ("vmInterface::createArea - got a new area (%x) from the areaPool\n",newArea);
foo=getAM();
newArea->setup(getAM());
newArea->createArea(AreaName,pageCount,address,addType,state,protect);
newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE
getAM()->addArea(newArea);
return newArea->getAreaID();
int retVal;
retVal = getAM()->createArea(AreaName,pageCount,address,addType,state,protect);
return retVal;
}
void vmInterface::freeArea(int Area)
void vmInterface::freeArea(int area)
{
//printf ("vmInterface::freeArea: begin\n");
area *oldArea=getAM()->findArea(Area);
//printf ("vmInterface::freeArea: found area %x\n",oldArea);
if (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");
vmBlock->areaPool->put(oldArea);
}
else
printf ("vmInterface::freeArea: unable to find requested area\n");
getAM()->freeArea(area);
}
status_t vmInterface::getAreaInfo(int Area,area_info *dest)
{
area *oldArea=getAM()->findArea(Area);
if (oldArea)
return oldArea->getInfo(dest);
else
printf ("vmInterface::getAreaInfo: unable to find requested area\n");
status_t retVal;
retVal = getAM()->getAreaInfo(Area,dest);
return retVal;
}
status_t vmInterface::getNextAreaInfo(int process,int32 *cookie,area_info *dest)
{
area *oldArea=getAM()->findArea(*cookie);
area *newArea=(area *)(oldArea->next);
if (newArea)
return newArea->getInfo(dest);
else
return B_BAD_VALUE;
status_t retVal;
// We *SHOULD* be getting the AM for this process. Something for HW integration time...
retVal = getAM()->getInfoAfter(*cookie,dest);
return retVal;
}
int vmInterface::getAreaByName(char *name)
{
return getAM()->findArea(name)->getAreaID();
int retVal;
retVal = getAM()->getAreaByName(name);
return retVal;
}
int vmInterface::cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType=ANY, pageState state=NO_LOCK, protectType prot=writable)
{
area *newArea = new (vmBlock->areaPool->get()) area;
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);
return newArea->getAreaID();
int retVal;
retVal = getAM()->cloneArea(newAreaID,AreaName,address, addType, state, prot);
return retVal;
}
void vmInterface::pager(void)
@@ -228,36 +199,14 @@ void vmInterface::cleaner(void)
void *vmInterface::mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
char name[MAXPATHLEN];
// Get the filename from fd...
strcpy( name,"mmap - need to include fileName");
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);
if (flags & MAP_ANON)
{
createArea(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr, addType ,LAZY,protType);
return addr;
}
area *newArea = new (vmBlock->areaPool->get()) area;
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
getAM()->addArea(newArea);
newArea->getAreaID();
//pageMan.dump();
//newArea->dump();
return addr;
void *retVal;
retVal = getAM()->mmap(addr,len,prot,flags,fd,offset);
return retVal;
}
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();
int retVal;
retVal = getAM()->munmap(addr,len);
return retVal;
}
+2 -1
View File
@@ -5,7 +5,6 @@
class vmInterface // This is the class that "owns" all of the managers.
{
private:
int nextAreaID;
areaManager *getAM(void); // This is for testing only...
public:
vmInterface(int pages);
@@ -28,6 +27,8 @@ class vmInterface // This is the class that "owns" all of the managers.
void pager(void);
void saver(void);
void cleaner(void);
status_t writeCachedBlock(int fd, size_t offset, void *data);
status_t readCachedBlock(int fd, size_t offset, void *data);
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
+1 -1
View File
@@ -29,7 +29,7 @@ vnode *poolvnode::get(void)
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)))));
unused.add(((node *)(newPage->getAddress()+(i*sizeof(vnode)))));
release_sem(inUse);
return (get()); // A little cheat - call self again to get the first one from stack...
}
+1 -1
View File
@@ -16,7 +16,7 @@ class poolvnode
void put(vnode *in)
{
acquire_sem(inUse);
unused.add(in);
unused.add((node *)in);
release_sem(inUse);
}
+20 -16
View File
@@ -1,6 +1,7 @@
#include "vpage.h"
#include "vnodePool.h"
#include "vmHeaderBlock.h"
#include "areaManager.h"
extern vmHeaderBlock *vmBlock;
@@ -33,7 +34,6 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
end_address=start+PAGE_SIZE-1;
protection=prot;
swappable=(state==NO_LOCK);
dirty=true;
if (backing)
{
@@ -50,6 +50,7 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
physMem->count++;
physPage=physMem;
}
dirty=(physPage!=NULL);
//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));
}
@@ -73,7 +74,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 = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
if (writeError)
{
dirty=true;
@@ -107,39 +108,42 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa
return true;
}
char vpage::getByte(unsigned long address)
char vpage::getByte(unsigned long address,areaManager *manager)
{
// printf ("vpage::getByte: address = %d\n",address );
//printf ("vpage::getByte: address = %ld\n",address );
if (!physPage)
if (!fault((void *)(address),false))
throw ("vpage::getByte",address,0);
// printf ("vpage::getByte: About to return %d\n", *((char *)(address-start_address+physPage->getAddress())));
if (!manager->fault((void *)(address),false))
throw ("vpage::getByte");
//printf ("vpage::getByte: 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)
void vpage::setByte(unsigned long address,char value,areaManager *manager)
{
// printf ("vpage::setByte: address = %d, value = %d\n",address, value);
if (!physPage)
if (!fault((void *)(address),true))
throw ("vpage::setByte",address,(int)value);
if (!manager->fault((void *)(address),true))
throw ("vpage::setByte");
*((char *)(address-start_address+physPage->getAddress()))=value;
// printf ("vpage::setByte: physical address = %d, value = %d\n",physPage->getAddress(), *((char *)(physPage->getAddress())));
}
int vpage::getInt(unsigned long address)
int vpage::getInt(unsigned long address,areaManager *manager)
{
printf ("vpage::getInt: address = %ld\n",address );
if (!physPage)
if (!fault((void *)(address),false))
throw ("vpage::getInt",address,0);
if (!manager->fault((void *)(address),false))
throw ("vpage::getInt");
printf ("vpage::getInt: About to return %d\n", *((char *)(address-start_address+physPage->getAddress())));
dump();
return *((int *)(address-start_address+physPage->getAddress()));
}
void vpage::setInt(unsigned long address,int value)
void vpage::setInt(unsigned long address,int value,areaManager *manager)
{
if (!physPage)
if (!fault((void *)(address),true))
throw ("vpage::setInt",address,value);
if (!manager->fault((void *)(address),true))
throw ("vpage::setInt");
*((int *)(address-start_address+physPage->getAddress()))=value;
}
+6 -5
View File
@@ -4,6 +4,7 @@
#include <pageManager.h>
#include <swapFileManager.h>
class areaManager;
class vpage : public node
{
private:
@@ -35,15 +36,15 @@ class vpage : public node
void dump(void)
{
printf ("Dumping vpage %x, address = %x, \n\t physPage: ",this,start_address);
printf ("Dumping vpage %p, address = %lx, \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
void setInt(unsigned long offset,int value); // This is for testing only
char getByte(unsigned long offset,areaManager *manager); // This is for testing only
void setByte(unsigned long offset,char value,areaManager *manager); // This is for testing only
int getInt(unsigned long offset,areaManager *manager); // This is for testing only
void setInt(unsigned long offset,int value,areaManager *manager); // This is for testing only
};
#endif
+19
View File
@@ -0,0 +1,19 @@
// This manager holds all of the vpages.
// It creates them from the vpage pool
// and ensures that no two vpages point to
// the same vnode without also pointing to
// the same physical memory. Thus, cached disk
// blocks and mmapped memory always stay in sync.
// mmap seems to not want this to happen for a
// couple of cases - MAP_PRIVATE and MAP_COPY.
// If we decided to ever build these, we would
// have to make some changes.
class vpageManager
{
private:
public:
vpage *getVpage(vnode &vn);
void putVpage(vpage &vp);
}
+1 -1
View File
@@ -30,7 +30,7 @@ vpage *poolvpage::get(void)
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)))));
unused.add(((node *)(newPage->getAddress()+(i*sizeof(vpage)))));
release_sem(inUse);
return (get()); // A little cheat - call self again to get the first one from stack...
}
+1 -1
View File
@@ -15,7 +15,7 @@ class poolvpage
void put(vpage *in)
{
acquire_sem(inUse);
unused.add(in);
unused.add((node *)in);
release_sem(inUse);
}