Checkpoint. Hand examined the code and made several changes/improvements.
Doesn't crash quite as easily. Still some nagging bugs. Partial implementation of hashTable. Need to make find use keys and do proper memory allocation (i.e. from physPages, not new). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1349 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
63ffaa3ea4
commit
a550db6753
@ -9,8 +9,14 @@
|
||||
|
||||
extern vmHeaderBlock *vmBlock;
|
||||
|
||||
bool vpageIsLessThan(void *a,void *b)
|
||||
{
|
||||
return (((reinterpret_cast<vpage *>(a))->getStartAddress()) < (reinterpret_cast<vpage *>(b))->getStartAddress());
|
||||
}
|
||||
|
||||
area::area(void)
|
||||
{
|
||||
vpages.setIsLessThan(vpageIsLessThan);
|
||||
}
|
||||
|
||||
void area::setup (areaManager *myManager)
|
||||
@ -20,10 +26,10 @@ void area::setup (areaManager *myManager)
|
||||
//error ("area::setup done setting up new area\n");
|
||||
}
|
||||
|
||||
unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount)
|
||||
unsigned long area::mapAddressSpecToAddress(addressSpec type,void * req,int pageCount)
|
||||
{
|
||||
// We will lock in the callers
|
||||
unsigned long base;
|
||||
unsigned long base,requested=(unsigned long)req;
|
||||
switch (type)
|
||||
{
|
||||
case EXACT:
|
||||
@ -48,92 +54,73 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque
|
||||
return base;
|
||||
}
|
||||
|
||||
status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset)
|
||||
{
|
||||
status_t area::createAreaGuts( char *inName, int pageCount, void **address, addressSpec type, pageState inState, protectType protect, bool inFinalWrite, int fd, size_t offset, area *originalArea=NULL /* For clone only*/)
|
||||
{
|
||||
strcpy(name,inName);
|
||||
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
|
||||
vpage *newPage;
|
||||
|
||||
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
|
||||
unsigned long base=mapAddressSpecToAddress(type,*address,pageCount);
|
||||
if (base==0)
|
||||
return B_ERROR;
|
||||
for (int i=0;i<pageCount;i++)
|
||||
{
|
||||
vnode *newVnode=new (vmBlock->vnodePool->get()) vnode;
|
||||
newVnode->fd=fd;
|
||||
newVnode->offset=offset+PAGE_SIZE*i;
|
||||
newVnode->valid=true;
|
||||
newPage=new (vmBlock->vpagePool->get()) vpage;
|
||||
newPage->setup(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
|
||||
vpages.add(newPage);
|
||||
// error ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset);
|
||||
}
|
||||
|
||||
state=inState;
|
||||
start_address=base;
|
||||
end_address=base+(pageCount*PAGE_SIZE)-1;
|
||||
*address=(void *)base;
|
||||
finalWrite=true;
|
||||
finalWrite=inFinalWrite;
|
||||
if (!originalArea)
|
||||
for (int i=0;i<pageCount;i++)
|
||||
{
|
||||
newPage=new (vmBlock->vpagePool->get()) vpage;
|
||||
if (fd)
|
||||
{
|
||||
vnode *newVnode=new (vmBlock->vnodePool->get()) vnode;
|
||||
newVnode->fd=fd;
|
||||
newVnode->offset=offset+PAGE_SIZE*i;
|
||||
newVnode->valid=true;
|
||||
newPage->setup(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
|
||||
}
|
||||
else
|
||||
newPage->setup(base+PAGE_SIZE*i,NULL,NULL,protect,inState);
|
||||
vpages.add(newPage);
|
||||
}
|
||||
else
|
||||
for (struct node *cur=originalArea->vpages.rock;cur;cur=cur->next)
|
||||
{
|
||||
vpage *page=(vpage *)cur;
|
||||
newPage=new (vmBlock->vpagePool->get()) vpage;
|
||||
newPage->setup(base,page->getBacking(),page->getPhysPage(),protect,inState);// Cloned area has the same physical page and backing store...
|
||||
vpages.add(newPage);
|
||||
base+=PAGE_SIZE;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset)
|
||||
{
|
||||
return createAreaGuts(inName,pageCount,address,type,inState,protect,true,fd,offset);
|
||||
}
|
||||
|
||||
status_t area::createArea(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect)
|
||||
{
|
||||
vpage *newPage;
|
||||
|
||||
strcpy(name,inName);
|
||||
state=inState;
|
||||
finalWrite=false;
|
||||
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
|
||||
|
||||
error ("area::createArea: Locked in createArea\n");
|
||||
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
|
||||
if (base==0)
|
||||
return B_ERROR;
|
||||
error ("area::createArea: base address = %ld\n",base);
|
||||
for (int i=0;i<pageCount;i++)
|
||||
{
|
||||
//error ("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);
|
||||
}
|
||||
start_address=base;
|
||||
end_address=base+(pageCount*PAGE_SIZE)-1;
|
||||
*address=(void *)base;
|
||||
error ("area::createArea: unlocked in createArea\n");
|
||||
return B_OK;
|
||||
return createAreaGuts(inName,pageCount,address,type,inState,protect,false,0,0);
|
||||
}
|
||||
|
||||
status_t area::cloneArea(area *origArea, char *inName, void **address, addressSpec type,pageState inState,protectType protect)
|
||||
{
|
||||
// error ("area::cloneArea: entered\n");
|
||||
strcpy(name,inName);
|
||||
int pageCount = origArea->getPageCount();
|
||||
// error ("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;
|
||||
// error ("area::cloneArea: base address = %x\n",base);
|
||||
|
||||
for (struct node *cur=origArea->vpages.rock;cur;)
|
||||
if (type==CLONE)
|
||||
{
|
||||
vpage *newPage,*page=(vpage *)cur;
|
||||
// Cloned area has the same physical page and backing store...
|
||||
newPage=new (vmBlock->vpagePool->get()) vpage;
|
||||
newPage->setup(base,page->getBacking(),page->getPhysPage(),protect,inState);
|
||||
vpages.add(newPage);
|
||||
base+=PAGE_SIZE;
|
||||
cur=cur->next;
|
||||
*address=(void *)(origArea->getStartAddress());
|
||||
type=EXACT;
|
||||
}
|
||||
state=inState;
|
||||
end_address=base+(pageCount*PAGE_SIZE)-1;
|
||||
*address=(void *)start_address;
|
||||
finalWrite=false;
|
||||
// error ("area::cloneArea: unlocked\n");
|
||||
return B_OK;
|
||||
if (origArea->getAreaManager()!=manager)
|
||||
{
|
||||
origArea->getAreaManager()->lock(); // This is just begging for a deadlock...
|
||||
status_t retVal = createAreaGuts(inName,origArea->getPageCount(),address,type,inState,protect,false,0,0,origArea);
|
||||
origArea->getAreaManager()->unlock();
|
||||
return retVal;
|
||||
}
|
||||
else
|
||||
return createAreaGuts(inName,origArea->getPageCount(),address,type,inState,protect,false,0,0,origArea);
|
||||
}
|
||||
|
||||
void area::freeArea(void)
|
||||
@ -184,7 +171,6 @@ status_t area::getInfo(area_info *dest)
|
||||
|
||||
bool area::contains(void *address)
|
||||
{
|
||||
// no need to lock here...
|
||||
unsigned long base=(unsigned long)(address);
|
||||
// error ("area::contains: looking for %d in %d -- %d, value = %d\n",base,start_address,end_address, ((start_address<=base) && (end_address>=base)));
|
||||
|
||||
@ -198,7 +184,7 @@ status_t area::resize(size_t newSize)
|
||||
return B_OK;
|
||||
if (newSize>oldSize)
|
||||
{
|
||||
int pageCount = (newSize-oldSize) / PAGE_SIZE;
|
||||
int pageCount = (newSize - oldSize + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
vpage *newPage;
|
||||
for (int i=0;i<pageCount;i++)
|
||||
{
|
||||
@ -210,7 +196,7 @@ status_t area::resize(size_t newSize)
|
||||
}
|
||||
else
|
||||
{
|
||||
int pageCount = (oldSize -newSize) / PAGE_SIZE;
|
||||
int pageCount = (oldSize - newSize + PAGE_SIZE - 1) / 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.
|
||||
@ -218,6 +204,8 @@ status_t area::resize(size_t newSize)
|
||||
for (cur=vpages.rock;cur->next;cur=cur->next); // INTENTIONAL - find the last one;
|
||||
oldPage=(vpage *)cur;
|
||||
vpages.remove(cur);
|
||||
if (finalWrite)
|
||||
oldPage->flush();
|
||||
oldPage->cleanup();
|
||||
vmBlock->vpagePool->put(oldPage);
|
||||
}
|
||||
@ -238,7 +226,6 @@ status_t area::setProtection(protectType prot)
|
||||
|
||||
vpage *area::findVPage(unsigned long address)
|
||||
{
|
||||
// No need to lock here...
|
||||
for (struct node *cur=vpages.rock;cur;cur=cur->next)
|
||||
{
|
||||
vpage *page=(vpage *)cur;
|
||||
@ -252,7 +239,6 @@ vpage *area::findVPage(unsigned long address)
|
||||
|
||||
bool area::fault(void *fault_address, bool writeError) // true = OK, false = panic.
|
||||
{
|
||||
// No need to lock here...
|
||||
vpage *page=findVPage((unsigned long)fault_address);
|
||||
if (page)
|
||||
return page->fault(fault_address,writeError);
|
||||
@ -262,7 +248,6 @@ bool area::fault(void *fault_address, bool writeError) // true = OK, false = pan
|
||||
|
||||
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,manager);
|
||||
@ -272,7 +257,6 @@ char area::getByte(unsigned long address) // This is for testing only
|
||||
|
||||
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,manager);
|
||||
@ -280,7 +264,6 @@ void area::setByte(unsigned long address,char value) // This is for testing only
|
||||
|
||||
int area::getInt(unsigned long address) // This is for testing only
|
||||
{
|
||||
// No need to lock here...
|
||||
vpage *page=findVPage(address);
|
||||
if (page)
|
||||
return page->getInt(address,manager);
|
||||
@ -290,7 +273,6 @@ int area::getInt(unsigned long address) // This is for testing only
|
||||
|
||||
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,manager);
|
||||
@ -298,7 +280,6 @@ void area::setInt(unsigned long address,int value) // This is for testing only
|
||||
|
||||
void area::pager(int desperation)
|
||||
{
|
||||
// No need to lock here...
|
||||
for (struct node *cur=vpages.rock;cur;cur=cur->next)
|
||||
{
|
||||
vpage *page=(vpage *)cur;
|
||||
@ -308,7 +289,6 @@ void area::pager(int desperation)
|
||||
|
||||
void area::saver(void)
|
||||
{
|
||||
// No need to lock here...
|
||||
for (struct node *cur=vpages.rock;cur;cur=cur->next)
|
||||
{
|
||||
vpage *page=(vpage *)cur;
|
||||
|
@ -28,7 +28,8 @@ class area : public node
|
||||
area(void);
|
||||
void setup(areaManager *myManager);
|
||||
bool nameMatch(char *matchName) {return (strcmp(matchName,name)==0);}
|
||||
unsigned long mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount);
|
||||
unsigned long mapAddressSpecToAddress(addressSpec type,void *requested,int pageCount);
|
||||
status_t createAreaGuts( char *inName, int pageCount, void **address, addressSpec type, pageState inState, protectType protect, bool inFinalWrite, int fd, size_t offset, area *originalArea=NULL /* For clone only*/);
|
||||
status_t createAreaMappingFile(char *name, int pageCount,void **address, addressSpec type,pageState state,protectType protect,int fd,size_t offset);
|
||||
status_t createArea (char *name, int pageCount,void **address, addressSpec type,pageState state,protectType protect);
|
||||
status_t cloneArea(area *area, char *inName, void **address, addressSpec type,pageState inState,protectType protect);
|
||||
|
@ -71,8 +71,8 @@ area *areaManager::findAreaLock(void *address)
|
||||
area *areaManager::findArea(char *address)
|
||||
{
|
||||
error ("Finding area by string\n");
|
||||
lock();
|
||||
area *retVal=NULL;
|
||||
lock();
|
||||
for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next)
|
||||
{
|
||||
area *myArea=(area *)cur;
|
||||
@ -125,13 +125,13 @@ bool areaManager::fault(void *fault_address, bool writeError) // true = OK, fals
|
||||
area *myArea;
|
||||
bool retVal;
|
||||
error ("Faulting \n");
|
||||
lock();
|
||||
// lock(); // Normally this should occur, but since we will be locked when we read/write anyway...
|
||||
myArea=findArea(fault_address);
|
||||
if (myArea)
|
||||
retVal= myArea->fault(fault_address,writeError);
|
||||
else
|
||||
retVal= false;
|
||||
unlock();
|
||||
// unlock();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@ -185,11 +185,13 @@ char areaManager::getByte(unsigned long address)
|
||||
{
|
||||
area *myArea;
|
||||
int retVal;
|
||||
lock();
|
||||
myArea=findArea((void *)address);
|
||||
if (myArea)
|
||||
retVal=myArea->getByte(address);
|
||||
else
|
||||
retVal= 0;
|
||||
unlock();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@ -197,28 +199,34 @@ int areaManager::getInt(unsigned long address)
|
||||
{
|
||||
area *myArea;
|
||||
int retVal;
|
||||
lock();
|
||||
myArea=findArea((void *)address);
|
||||
if (myArea)
|
||||
retVal=myArea->getInt(address);
|
||||
else
|
||||
retVal= 0;
|
||||
unlock();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void areaManager::setByte(unsigned long address,char value)
|
||||
{
|
||||
area *myArea;
|
||||
lock();
|
||||
myArea=findArea((void *)address);
|
||||
if (myArea)
|
||||
myArea->setByte(address,value);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void areaManager::setInt(unsigned long address,int value)
|
||||
{
|
||||
area *myArea;
|
||||
lock();
|
||||
myArea=findArea((void *)address);
|
||||
if (myArea)
|
||||
myArea->setInt(address,value);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void areaManager::pager(int desperation)
|
||||
@ -275,3 +283,24 @@ void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off
|
||||
unlock();
|
||||
return addr;
|
||||
}
|
||||
|
||||
status_t areaManager::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();
|
||||
area *myArea=findArea(addr);
|
||||
if (myArea)
|
||||
{
|
||||
removeArea(myArea);
|
||||
myArea->freeArea();
|
||||
vmBlock->areaPool->put(myArea);
|
||||
}
|
||||
else
|
||||
{
|
||||
error ("areaManager::munmap: unable to find requested area\n");
|
||||
retVal=B_ERROR;
|
||||
}
|
||||
unlock();
|
||||
return retVal;
|
||||
}
|
||||
|
@ -87,25 +87,10 @@ class areaManager // One of these per process
|
||||
int createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) ;
|
||||
void pager(int desperation);
|
||||
void saver(void);
|
||||
void lock()
|
||||
{
|
||||
static long lockCount=0;
|
||||
if (!((lockCount++)%200))
|
||||
error ("locking\n");
|
||||
acquire_sem(myLock);
|
||||
}
|
||||
void unlock() {/*error ("unlocking\n");*/release_sem(myLock);}
|
||||
void lock() { acquire_sem(myLock); }
|
||||
void unlock() {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;
|
||||
}
|
||||
status_t munmap(void *addr,size_t len);
|
||||
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.
|
||||
|
64
src/kernel/vm2/hashTable.h
Normal file
64
src/kernel/vm2/hashTable.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef _HASH_H
|
||||
#define _HASH_H
|
||||
#include "list.h"
|
||||
|
||||
static bool throwException (node &foo)
|
||||
{ throw ("Attempting to use an hash table without setting up a 'hash' function"); }
|
||||
|
||||
class hashTable : public list
|
||||
{
|
||||
public:
|
||||
hashTable(int size)
|
||||
{
|
||||
nodeCount=0;
|
||||
numRocks=size;
|
||||
int pageCount=PAGE_SIZE*size/sizeof(list);
|
||||
page *newPage=vmBlock->pageMan->getPage();
|
||||
if (!newPage)
|
||||
throw ("Out of pages to allocate a pool!");
|
||||
int newCount=PAGE_SIZE/sizeof(area);
|
||||
acquire_sem(inUse);
|
||||
//error ("poolarea::get: Adding %d new elements to the pool!\n",newCount);
|
||||
for (int i=0;i<newCount;i++)
|
||||
unused.add(((node *)(newPage->getAddress()+(i*sizeof(area)))));
|
||||
release_sem(inUse);
|
||||
}
|
||||
|
||||
void setHash (ulong (*hash_in)(node &)) { hash=hash_in; }
|
||||
void setIsEqual (ulong (*isEqual_in)(node &,node &)) { isEqual=isEqual_in; }
|
||||
|
||||
int count(void) {return nodeCount;}
|
||||
void add (node *newNode) {
|
||||
unsigned long hashValue=hash(*newNode)%numRocks;
|
||||
// Note - no looking for duplicates; no ordering.
|
||||
rocks[hashValue].add(newNode);
|
||||
}
|
||||
node *next(void) { return NULL; // This operation doesn't make sense for this class}
|
||||
void remove(node *toNuke)
|
||||
{
|
||||
unsigned long hashValue=hash(*findNode)%numRocks;
|
||||
rocks[hashValue].remove(newNode);
|
||||
}
|
||||
void dump(void)
|
||||
{
|
||||
for (int i=0;i<numRocks;i++)
|
||||
for (struct node *cur=rocks[hashValue].rock;cur && !done;cur=cur->next)
|
||||
error ("hashTable::dump: At %p, next = %p\n",cur,cur->next);
|
||||
}
|
||||
node *find(node *findNode)
|
||||
{
|
||||
unsigned long hashValue=hash(*findNode)%numRocks;
|
||||
for (struct node *cur=rocks[hashValue].rock;cur && !done;cur=cur->next)
|
||||
if (isEqual(*findNode,*cur))
|
||||
return cur;
|
||||
return NULL;
|
||||
}
|
||||
private:
|
||||
ulong (*hash)(node &a);
|
||||
bool (*isEqual)(node &a,node &b);
|
||||
list *rocks;
|
||||
int numRocks;
|
||||
|
||||
|
||||
};
|
||||
#endif
|
@ -54,7 +54,7 @@ page *pageManager::getPage(void)
|
||||
release_sem(cleanLock);
|
||||
//error ("pageManager::getPage:unlocked clean\n");
|
||||
} // This could fail if someone swooped in and stole our page.
|
||||
else if (unused.count())
|
||||
if (!ret && unused.count())
|
||||
{
|
||||
//error ("pageManager::getPage:Checking unused\n");
|
||||
acquire_sem(unusedLock);
|
||||
@ -76,7 +76,7 @@ page *pageManager::getPage(void)
|
||||
|
||||
void pageManager::freePage(page *toFree)
|
||||
{
|
||||
error ("Inside freePage; old value = %d",toFree->count);
|
||||
error ("pageManager::freePage; old value = %d\n",toFree->count);
|
||||
if (atomic_add(&(toFree->count),-1)==1) // atomic_add returns the *PREVIOUS* value. So we need to check to see if the one we are wasting was the last one.
|
||||
{
|
||||
acquire_sem(inUseLock);
|
||||
@ -86,25 +86,28 @@ void pageManager::freePage(page *toFree)
|
||||
unused.add(toFree);
|
||||
release_sem(unusedLock);
|
||||
}
|
||||
error (" new value = %d, page = %x\n",toFree->count,toFree->getAddress());
|
||||
error ("pageManager::freePage:new value = %d, page = %x\n",toFree->count,toFree->getAddress());
|
||||
}
|
||||
|
||||
void pageManager::cleaner(void)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
snooze(250000);
|
||||
if (unused.count())
|
||||
{
|
||||
//error ("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);
|
||||
if (first)
|
||||
{
|
||||
first->zero();
|
||||
acquire_sem(cleanLock);
|
||||
clean.add(first);
|
||||
release_sem(cleanLock);
|
||||
}
|
||||
//error ("pageManager::cleaner: All done with vacuum a page\n");
|
||||
snooze(125000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,13 +122,16 @@ int pageManager::desperation(void)
|
||||
void pageManager::dump(void)
|
||||
{
|
||||
error ("Dumping the unused list\n");
|
||||
acquire_sem(unusedLock);
|
||||
for (struct node *cur=unused.rock;cur;)
|
||||
{
|
||||
page *thisPage=(page *)cur;
|
||||
thisPage->dump();
|
||||
cur=cur->next;
|
||||
}
|
||||
release_sem(unusedLock);
|
||||
error ("Dumping the clean list\n");
|
||||
acquire_sem(cleanLock);
|
||||
for (struct node *cur=clean.rock;cur;)
|
||||
{
|
||||
page *thisPage=(page *)cur;
|
||||
@ -133,10 +139,13 @@ void pageManager::dump(void)
|
||||
cur=cur->next;
|
||||
}
|
||||
error ("Dumping the inuse list\n");
|
||||
release_sem(cleanLock);
|
||||
acquire_sem(inUseLock);
|
||||
for (struct node *cur=inUse.rock;cur;)
|
||||
{
|
||||
page *thisPage=(page *)cur;
|
||||
thisPage->dump();
|
||||
cur=cur->next;
|
||||
}
|
||||
release_sem(inUseLock);
|
||||
}
|
||||
|
@ -16,26 +16,6 @@ swapFileManager::swapFileManager(void)
|
||||
lockFreeList=create_sem(1,"SwapFile Free List Semaphore"); // Should have team name in it.
|
||||
}
|
||||
|
||||
void swapFileManager::write_block(vnode &node,void *loc,unsigned long size)
|
||||
{
|
||||
//error ("swapFileManager::write_block: writing, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc);
|
||||
if (-1==lseek(node.fd,node.offset,SEEK_SET))
|
||||
error ("seek failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno));
|
||||
if (-1==write(node.fd,loc,size))
|
||||
error ("Write failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno));
|
||||
node.valid=true;
|
||||
//error ("swapFileManager::write_block: done, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc);
|
||||
}
|
||||
|
||||
void swapFileManager::read_block(vnode &node,void *loc,unsigned long size)
|
||||
{
|
||||
if (node.valid==false)
|
||||
return; // Do nothing. This prevents "garbage" data on disk from being read in...
|
||||
//error ("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);
|
||||
}
|
||||
|
||||
vnode &swapFileManager::findNode(void)
|
||||
{
|
||||
//error ("swapFileManager::findNode: Entering findNode \n");
|
||||
@ -43,10 +23,10 @@ vnode &swapFileManager::findNode(void)
|
||||
//error ("swapFileManager::findNode: Finding a new node for you, Master: ");
|
||||
vnode *newNode;
|
||||
//error ("locking in sfm\n");
|
||||
Lock();
|
||||
lock();
|
||||
newNode=reinterpret_cast<vnode *>(swapFileFreeList.next());
|
||||
//error ("unlocking in sfm\n");
|
||||
Unlock();
|
||||
unlock();
|
||||
if (!newNode)
|
||||
{
|
||||
newNode=new (vmBlock->vnodePool->get()) vnode;
|
||||
@ -63,15 +43,14 @@ vnode &swapFileManager::findNode(void)
|
||||
|
||||
void swapFileManager::freeVNode(vnode &v)
|
||||
{
|
||||
v.count--;
|
||||
if (v.count==0)
|
||||
if ( atomic_add(&v.count,-1)==1)
|
||||
{
|
||||
//error ("locking in sfm\n");
|
||||
Lock();
|
||||
lock();
|
||||
//error ("swapFileManager::freeNode: Starting Freeing a new node for you, Master: offset:%d\n",v.offset);
|
||||
v.valid=false;
|
||||
swapFileFreeList.add(&v);
|
||||
//error ("unlocking in sfm\n");
|
||||
Unlock();
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ class swapFileManager {
|
||||
void freeVNode(vnode &); // Free a node
|
||||
void write_block(vnode &node,void *loc,unsigned long size);
|
||||
void read_block(vnode &node,void *loc,unsigned long size);
|
||||
void Lock() {acquire_sem(lockFreeList);}
|
||||
void Unlock() {release_sem(lockFreeList);}
|
||||
void lock() {acquire_sem(lockFreeList);}
|
||||
void unlock() {release_sem(lockFreeList);}
|
||||
int getFD(void) {return swapFile;}
|
||||
};
|
||||
#endif
|
||||
|
@ -71,6 +71,7 @@ struct loopTestParameters
|
||||
|
||||
int32 loopTest(void *parameters)
|
||||
{
|
||||
try{
|
||||
error ("Starting Loop Test!\n");
|
||||
loopTestParameters *params=((loopTestParameters *)parameters);
|
||||
int area1;
|
||||
@ -86,6 +87,12 @@ int32 loopTest(void *parameters)
|
||||
snooze(params->loopSnooze);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error ("Exception thrown!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int32 getInfoTest(void *parameters)
|
||||
{
|
||||
@ -93,6 +100,7 @@ int32 getInfoTest(void *parameters)
|
||||
area_info ai;
|
||||
int area1;
|
||||
|
||||
try{
|
||||
while (1)
|
||||
{
|
||||
snooze(params->initialSnooze);
|
||||
@ -117,9 +125,16 @@ int32 getInfoTest(void *parameters)
|
||||
snooze(params->loopSnooze);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error ("Exception thrown!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int32 mmapTest (void *parameters)
|
||||
{
|
||||
try{
|
||||
void *map;
|
||||
loopTestParameters *params=((loopTestParameters *)parameters);
|
||||
int size=params->areaSize; // Note that this is in bytes, not in pages
|
||||
@ -145,13 +160,19 @@ int32 mmapTest (void *parameters)
|
||||
error ("Closed file, fd = %d\n",fd);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error ("Exception thrown!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int32 cloneTest (void *parameters)
|
||||
{
|
||||
loopTestParameters *params=((loopTestParameters *)parameters);
|
||||
int area1,area2;
|
||||
void *cloneAddr=NULL;
|
||||
|
||||
try {
|
||||
while (1)
|
||||
{
|
||||
snooze(params->initialSnooze);
|
||||
@ -170,6 +191,12 @@ int32 cloneTest (void *parameters)
|
||||
snooze(params->loopSnooze);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error ("Exception thrown!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
@ -184,8 +211,8 @@ int main(int argc,char **argv)
|
||||
resume_thread(loop2=spawn_thread(loopTest,"area test 2",0,&area2Params));
|
||||
resume_thread(loop3=spawn_thread(loopTest,"area test 3",0,&area3Params));
|
||||
resume_thread(info1=spawn_thread(getInfoTest,"info test 1",0,&info1Params));
|
||||
resume_thread(mmap1=spawn_thread(mmapTest,"mmap test 1",0,&mmap1Params));
|
||||
resume_thread(clone1=spawn_thread(cloneTest,"clone test 1",0,&clone1Params));
|
||||
//resume_thread(mmap1=spawn_thread(mmapTest,"mmap test 1",0,&mmap1Params));
|
||||
//resume_thread(clone1=spawn_thread(cloneTest,"clone test 1",0,&clone1Params));
|
||||
|
||||
snooze(1000000000);
|
||||
|
||||
|
@ -133,7 +133,9 @@ status_t vmInterface::resizeArea(int Area,size_t size)
|
||||
int vmInterface::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect)
|
||||
{
|
||||
int retVal;
|
||||
error ("vmInterface::createArea: Creating an area!\n");
|
||||
retVal = getAM()->createArea(AreaName,pageCount,address,addType,state,protect);
|
||||
error ("vmInterface::createArea: Done creating an area!\n");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@ -145,7 +147,9 @@ void vmInterface::freeArea(int area)
|
||||
status_t vmInterface::getAreaInfo(int Area,area_info *dest)
|
||||
{
|
||||
status_t retVal;
|
||||
error ("vmInterface::getAreaInfo: Getting info about an area!\n");
|
||||
retVal = getAM()->getAreaInfo(Area,dest);
|
||||
error ("vmInterface::getAreaInfo: Done getting info about an area!\n");
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -2,18 +2,35 @@
|
||||
#include "vnodePool.h"
|
||||
#include "vmHeaderBlock.h"
|
||||
#include "areaManager.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
extern vmHeaderBlock *vmBlock;
|
||||
extern vmHeaderBlock *vmBlock;
|
||||
|
||||
void vpage::flush(void)
|
||||
{
|
||||
if (protection==writable && dirty)
|
||||
vmBlock->swapMan->write_block(*backingNode,((void *)(physPage->getAddress())), PAGE_SIZE);
|
||||
{
|
||||
//error (vpage::write_block: writing, backingNode->fd = %d, backingNode->offset = %d, address = %x\n",backingNode->fd, backingNode->offset,loc);
|
||||
if (-1==lseek(backingNode->fd,backingNode->offset,SEEK_SET))
|
||||
error ("vpage::flush:seek failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno));
|
||||
if (-1==write(backingNode->fd,(void *)start_address,PAGE_SIZE))
|
||||
error ("vpage::flush: failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno));
|
||||
backingNode->valid=true;
|
||||
//error ("vpage::write_block: done, backingNode->fd = %d, backingNode->offset = %d, address = %x\n",backingNode->fd, backingNode->offset,loc);
|
||||
}
|
||||
}
|
||||
|
||||
void vpage::refresh(void)
|
||||
{
|
||||
vmBlock->swapMan->read_block(*backingNode,((void *)(physPage->getAddress())), PAGE_SIZE);
|
||||
if (backingNode->valid==false)
|
||||
return; // Do nothing. This prevents "garbage" data on disk from being read in...
|
||||
//error ("vpage::refresh: reading, backingNode->fd = %d, backingNode->offset = %d into %x\n",backingNode->fd, backingNode->offset,loc);
|
||||
if (-1==lseek(backingNode->fd,backingNode->offset,SEEK_SET))
|
||||
error ("vpage::refresh: seek failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno));
|
||||
if (-1==read(backingNode->fd,(void *)start_address,PAGE_SIZE))
|
||||
error ("vpage::refresh: failed, fd = %d, errno = %d, %s\n",backingNode->fd,errno,strerror(errno));
|
||||
}
|
||||
|
||||
vpage::vpage(void)
|
||||
@ -50,7 +67,7 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
|
||||
atomic_add(&(physMem->count),1);
|
||||
physPage=physMem;
|
||||
}
|
||||
dirty=(physPage!=NULL);
|
||||
dirty=false;
|
||||
//error ("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));
|
||||
}
|
||||
|
||||
@ -61,8 +78,13 @@ void vpage::cleanup(void)
|
||||
if (backingNode)
|
||||
{
|
||||
if (backingNode->fd)
|
||||
vmBlock->swapMan->freeVNode(*backingNode);
|
||||
vmBlock->vnodePool->put(backingNode);
|
||||
if (backingNode->fd==vmBlock->swapMan->getFD())
|
||||
vmBlock->swapMan->freeVNode(*backingNode);
|
||||
else
|
||||
{
|
||||
if ( atomic_add(&(backingNode->count),-1)==1)
|
||||
vmBlock->vnodePool->put(backingNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,24 +97,21 @@ 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
|
||||
error ("vpage::fault: virtual address = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
|
||||
if (writeError)
|
||||
if (writeError && physPage)
|
||||
{
|
||||
if (physPage)
|
||||
dirty=true;
|
||||
if (protection==copyOnWrite) // Else, this was just a "let me know when I am dirty"...
|
||||
{
|
||||
dirty=true;
|
||||
if (protection==copyOnWrite) // Else, this was just a "let me know when I am dirty"...
|
||||
{
|
||||
page *newPhysPage=vmBlock->pageMan->getPage();
|
||||
if (!newPhysPage) // No room at the inn
|
||||
return false;
|
||||
memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE);
|
||||
physPage=newPhysPage;
|
||||
protection=writable;
|
||||
backingNode=&(vmBlock->swapMan->findNode()); // Need new backing store for this node, since it was copied, the original is no good...
|
||||
// Update the architecture specific stuff here...
|
||||
}
|
||||
return true;
|
||||
page *newPhysPage=vmBlock->pageMan->getPage();
|
||||
if (!newPhysPage) // No room at the inn
|
||||
return false;
|
||||
memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE);
|
||||
physPage=newPhysPage;
|
||||
protection=writable;
|
||||
backingNode=&(vmBlock->swapMan->findNode()); // Need new backing store for this node, since it was copied, the original is no good...
|
||||
// Update the architecture specific stuff here...
|
||||
}
|
||||
return true;
|
||||
}
|
||||
physPage=vmBlock->pageMan->getPage();
|
||||
if (!physPage) // No room at the inn
|
||||
@ -102,7 +121,7 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa
|
||||
// This refresh is unneeded if the data was never written out...
|
||||
dump();
|
||||
refresh(); // I wonder if these vnode calls are safe during an interrupt...
|
||||
dirty=true;
|
||||
dirty=false;
|
||||
error ("vpage::fault: Refreshed\n");
|
||||
dump();
|
||||
error ("vpage::fault: exiting\n");
|
||||
|
Loading…
Reference in New Issue
Block a user