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:
+38
-38
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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...
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class poolarea
|
||||
void put(area *in)
|
||||
{
|
||||
acquire_sem(inUse);
|
||||
unused.add(in);
|
||||
unused.add((node *)in);
|
||||
release_sem(inUse);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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...
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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...
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class poolvpage
|
||||
void put(vpage *in)
|
||||
{
|
||||
acquire_sem(inUse);
|
||||
unused.add(in);
|
||||
unused.add((node *)in);
|
||||
release_sem(inUse);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user