More improvements. Does not run all tests, though - still have some locking issues
around clone area, I think. Still, much improved... git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1048 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
SubDir OBOS_TOP src kernel vm2 ;
|
||||
|
||||
BinCommand vmTest : area.C areaManager.C cacheManager.C page.C pageManager.C swapFileManager.C test.C vmInterface.C vpage.C : root be ;
|
||||
BinCommand vmTest : error.C area.C areaManager.C cacheManager.C page.C pageManager.C swapFileManager.C test.C vmInterface.C vpage.C areaPool.C vnodePool.C vpagePool.C : root be ;
|
||||
BinCommand olTest : error.C olTest.C : root be ;
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -14,7 +14,8 @@
|
||||
paging
|
||||
disk caching
|
||||
|
||||
5) Improve locking (remains to be seen - works ok so far)
|
||||
6) See how unresolvable page faults and permissions errors are handled - need to properly handle
|
||||
- This may have to come at HW integration time, since they will be app signals, etc...
|
||||
7) There is no arch-level integration. This is to be tested (to death) in user land first. * == can not be done in user land.
|
||||
8) Add statistics counting for copy in/out
|
||||
9) Must lock original area when clone()ing. Sigh.
|
||||
|
||||
+20
-20
@@ -15,9 +15,9 @@ area::area(void)
|
||||
|
||||
void area::setup (areaManager *myManager)
|
||||
{
|
||||
//printf ("area::setup setting up new area\n");
|
||||
//error ("area::setup setting up new area\n");
|
||||
manager=myManager;
|
||||
//printf ("area::setup done setting up new area\n");
|
||||
//error ("area::setup done setting up new area\n");
|
||||
}
|
||||
|
||||
unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount)
|
||||
@@ -44,7 +44,7 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque
|
||||
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);
|
||||
// error ("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;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ status_t area::createAreaMappingFile(char *inName, int pageCount,void **address,
|
||||
newPage=new (vmBlock->vpagePool->get()) vpage;
|
||||
newPage->setup(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
|
||||
vpages.add(newPage);
|
||||
// printf ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset);
|
||||
// error ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset);
|
||||
}
|
||||
|
||||
state=inState;
|
||||
@@ -86,14 +86,14 @@ 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...
|
||||
|
||||
// printf ("area::createArea: Locked in createArea\n");
|
||||
error ("area::createArea: Locked in createArea\n");
|
||||
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
|
||||
if (base==0)
|
||||
return B_ERROR;
|
||||
// printf ("area::createArea: base address = %ld\n",base);
|
||||
error ("area::createArea: base address = %ld\n",base);
|
||||
for (int i=0;i<pageCount;i++)
|
||||
{
|
||||
//printf ("in area::createArea: creating page = %d\n",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);
|
||||
@@ -101,22 +101,22 @@ status_t area::createArea(char *inName, int pageCount,void **address, addressSpe
|
||||
start_address=base;
|
||||
end_address=base+(pageCount*PAGE_SIZE)-1;
|
||||
*address=(void *)base;
|
||||
// printf ("area::createArea: unlocked in createArea\n");
|
||||
error ("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)
|
||||
{
|
||||
// printf ("area::cloneArea: entered\n");
|
||||
// error ("area::cloneArea: entered\n");
|
||||
strcpy(name,inName);
|
||||
int pageCount = origArea->getPageCount();
|
||||
// printf ("area::cloneArea: locked\n");
|
||||
// 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;
|
||||
// printf ("area::cloneArea: base address = %x\n",base);
|
||||
// error ("area::cloneArea: base address = %x\n",base);
|
||||
|
||||
for (struct node *cur=origArea->vpages.rock;cur;)
|
||||
{
|
||||
@@ -132,29 +132,29 @@ status_t area::cloneArea(area *origArea, char *inName, void **address, addressSp
|
||||
end_address=base+(pageCount*PAGE_SIZE)-1;
|
||||
*address=(void *)start_address;
|
||||
finalWrite=false;
|
||||
// printf ("area::cloneArea: unlocked\n");
|
||||
// error ("area::cloneArea: unlocked\n");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void area::freeArea(void)
|
||||
{
|
||||
//printf ("area::freeArea: starting \n");
|
||||
//error ("area::freeArea: starting \n");
|
||||
|
||||
// vpages.dump();
|
||||
node *cur;
|
||||
while ((cur=vpages.next())!=NULL)
|
||||
{
|
||||
//printf ("area::freeArea: wasting a page: %x\n",cur);
|
||||
//error ("area::freeArea: wasting a page: %x\n",cur);
|
||||
vpage *page=reinterpret_cast<vpage *>(cur);
|
||||
if (finalWrite)
|
||||
page->flush();
|
||||
//printf ("area::freeArea: flushed a page \n");
|
||||
//error ("area::freeArea: flushed a page \n");
|
||||
page->cleanup();
|
||||
//page->next=NULL;
|
||||
vmBlock->vpagePool->put(page);
|
||||
}
|
||||
//printf ("area::freeArea: unlocking \n");
|
||||
//printf ("area::freeArea: ending \n");
|
||||
//error ("area::freeArea: unlocking \n");
|
||||
//error ("area::freeArea: ending \n");
|
||||
}
|
||||
|
||||
status_t area::getInfo(area_info *dest)
|
||||
@@ -186,7 +186,7 @@ bool area::contains(void *address)
|
||||
{
|
||||
// no need to lock here...
|
||||
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)));
|
||||
// error ("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) && (base<=end_address));
|
||||
}
|
||||
@@ -242,7 +242,7 @@ 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);
|
||||
//error ("Examining following vpage, looking for address %lx\n",address);
|
||||
//page->dump();
|
||||
if (page->contains(address))
|
||||
return page;
|
||||
@@ -318,7 +318,7 @@ void area::saver(void)
|
||||
|
||||
void area::dump(void)
|
||||
{
|
||||
printf ("area::dump: size = %ld, lock = %d, address = %lx\n",end_address-start_address,state,start_address);
|
||||
error ("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;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "OS.h"
|
||||
#include "vm.h"
|
||||
#include "list.h"
|
||||
#include "olist.h"
|
||||
|
||||
class areaManager;
|
||||
class vpage;
|
||||
@@ -10,12 +11,12 @@ class vpage;
|
||||
class area : public node
|
||||
{
|
||||
protected:
|
||||
list vpages;
|
||||
orderedList vpages;
|
||||
char name[B_OS_NAME_LENGTH];
|
||||
pageState state;
|
||||
protectType protection;
|
||||
bool finalWrite;
|
||||
int areaID;
|
||||
area_id areaID;
|
||||
int in_count;
|
||||
int out_count;
|
||||
int copy_count;
|
||||
|
||||
@@ -28,7 +28,7 @@ unsigned long areaManager::getNextAddress(int pages, unsigned long start)
|
||||
if (cur)
|
||||
{
|
||||
area *myArea=(area *)cur;
|
||||
// printf ("Looking for %x, %d pages; current = %x\n",start,pages,myArea->getEndAddress());
|
||||
// error ("Looking for %x, %d pages; current = %x\n",start,pages,myArea->getEndAddress());
|
||||
if (!myArea->couldAdd(start,end))
|
||||
{ // if we don't work, there must be an overlap, so go to the end of this area.
|
||||
start=myArea->getEndAddress();
|
||||
@@ -39,24 +39,24 @@ unsigned long areaManager::getNextAddress(int pages, unsigned long start)
|
||||
return start;
|
||||
}
|
||||
|
||||
void areaManager::freeArea(int areaID)
|
||||
void areaManager::freeArea(area_id areaID)
|
||||
{
|
||||
printf ("areaManager::freeArea: begin\n");
|
||||
error ("areaManager::freeArea: begin\n");
|
||||
lock();
|
||||
area *oldArea=findArea(areaID);
|
||||
//printf ("areaManager::freeArea: found area %x\n",oldArea);
|
||||
//error ("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);
|
||||
// error ("areaManager::freeArea: removing area %x from linked list\n",oldArea);
|
||||
// error ("areaManager::freeArea: areaManager = %x \n",manager);
|
||||
removeArea(oldArea);
|
||||
// printf ("areaManager::freeArea: deleting area %x \n",oldArea);
|
||||
// error ("areaManager::freeArea: deleting area %x \n",oldArea);
|
||||
oldArea->freeArea();
|
||||
// printf ("areaManager::freeArea: freeArea complete \n");
|
||||
// error ("areaManager::freeArea: freeArea complete \n");
|
||||
vmBlock->areaPool->put(oldArea);
|
||||
}
|
||||
else
|
||||
printf ("areaManager::freeArea: unable to find requested area\n");
|
||||
error ("areaManager::freeArea: unable to find requested area\n");
|
||||
unlock();
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ area *areaManager::findAreaLock(void *address)
|
||||
|
||||
area *areaManager::findArea(char *address)
|
||||
{
|
||||
printf ("Finding area by string\n");
|
||||
error ("Finding area by string\n");
|
||||
lock();
|
||||
area *retVal=NULL;
|
||||
for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next)
|
||||
@@ -86,22 +86,21 @@ area *areaManager::findArea(char *address)
|
||||
area *areaManager::findArea(void *address)
|
||||
{
|
||||
// THIS DOES NOT HAVE LOCKING - all callers must lock.
|
||||
//printf ("Finding area by void * address\n");
|
||||
//error ("Finding area by void * address\n");
|
||||
for (struct node *cur=areas.rock;cur;cur=cur->next)
|
||||
{
|
||||
area *myArea=(area *)cur;
|
||||
// printf ("areaManager::findArea: Looking for %x between %x and %x\n",address,myArea->getStartAddress(),myArea->getEndAddress());
|
||||
fflush(NULL);
|
||||
// error ("areaManager::findArea: Looking for %x between %x and %x\n",address,myArea->getStartAddress(),myArea->getEndAddress());
|
||||
if (myArea->contains(address))
|
||||
return myArea;
|
||||
}
|
||||
printf ("areaManager::findArea is giving up\n");
|
||||
error ("areaManager::findArea is giving up\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
area *areaManager::findAreaLock(area_id id)
|
||||
{
|
||||
printf ("Finding area by areaID \n");
|
||||
error ("Finding area by areaID \n");
|
||||
lock();
|
||||
area *retVal=findArea(id);
|
||||
unlock();
|
||||
@@ -110,7 +109,7 @@ area *areaManager::findAreaLock(area_id id)
|
||||
|
||||
area *areaManager::findArea(area_id id)
|
||||
{
|
||||
//printf ("Finding area by area_id\n");
|
||||
//error ("Finding area by area_id\n");
|
||||
area *retVal=NULL;
|
||||
for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next)
|
||||
{
|
||||
@@ -125,7 +124,7 @@ bool areaManager::fault(void *fault_address, bool writeError) // true = OK, fals
|
||||
{
|
||||
area *myArea;
|
||||
bool retVal;
|
||||
printf ("Faulting \n");
|
||||
error ("Faulting \n");
|
||||
lock();
|
||||
myArea=findArea(fault_address);
|
||||
if (myArea)
|
||||
@@ -136,40 +135,48 @@ bool areaManager::fault(void *fault_address, bool writeError) // true = OK, fals
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int areaManager::nextAreaID=0;
|
||||
long areaManager::nextAreaID=0;
|
||||
|
||||
int areaManager::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect)
|
||||
{
|
||||
printf ("Creating an area\n");
|
||||
error ("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);
|
||||
// error ("areaManager::createArea - got a new area (%p) from the areaPool\n",newArea);
|
||||
newArea->setup(this);
|
||||
// printf ("areaManager::createArea - setup complete\n");
|
||||
// error ("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");
|
||||
// error ("areaManager::createArea - new area's createArea called\n");
|
||||
atomic_add(&nextAreaID,1);
|
||||
newArea->setAreaID(nextAreaID);
|
||||
// error ("areaManager::createArea - new area's setAreaID called\n");
|
||||
addArea(newArea);
|
||||
// printf ("areaManager::createArea - new area added to list\n");
|
||||
// error ("areaManager::createArea - new area added to list\n");
|
||||
int retVal=newArea->getAreaID();
|
||||
// printf ("areaManager::createArea - new area id found\n");
|
||||
// error ("areaManager::createArea - new area id found\n");
|
||||
unlock();
|
||||
//printf ("Done Creating an area\n");
|
||||
//error ("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");
|
||||
int retVal;
|
||||
error ("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();
|
||||
if (oldArea)
|
||||
{
|
||||
area *newArea = new (vmBlock->areaPool->get()) area;
|
||||
newArea->setup(this);
|
||||
newArea->cloneArea(oldArea,AreaName,address,addType,state,protect);
|
||||
atomic_add(&nextAreaID,1);
|
||||
newArea->setAreaID(nextAreaID);
|
||||
addArea(newArea);
|
||||
retVal=newArea->getAreaID();
|
||||
}
|
||||
else
|
||||
retVal=B_ERROR;
|
||||
unlock();
|
||||
return retVal;
|
||||
}
|
||||
@@ -220,7 +227,7 @@ void areaManager::pager(int desperation)
|
||||
for (struct node *cur=areas.rock;cur;cur=cur->next)
|
||||
{
|
||||
area *myArea=(area *)cur;
|
||||
//printf ("areaManager::pager; area = \n");
|
||||
//error ("areaManager::pager; area = \n");
|
||||
//myArea->dump();
|
||||
myArea->pager(desperation);
|
||||
}
|
||||
@@ -247,7 +254,7 @@ void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off
|
||||
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);
|
||||
//error ("flags = %x, anon = %x\n",flags,MAP_ANON);
|
||||
lock();
|
||||
if (flags & MAP_ANON)
|
||||
{
|
||||
@@ -257,9 +264,10 @@ void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off
|
||||
|
||||
area *newArea = new (vmBlock->areaPool->get()) area;
|
||||
newArea->setup(this);
|
||||
//printf ("area = %x, start = %x\n",newArea, newArea->getStartAddress());
|
||||
//error ("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
|
||||
atomic_add(&nextAreaID,1);
|
||||
newArea->setAreaID(nextAreaID);
|
||||
addArea(newArea);
|
||||
newArea->getAreaID();
|
||||
//pageMan.dump();
|
||||
|
||||
@@ -7,12 +7,12 @@ class areaManager // One of these per process
|
||||
orderedList areas;
|
||||
team_id team;
|
||||
sem_id myLock;
|
||||
static int nextAreaID;
|
||||
static long nextAreaID;
|
||||
public:
|
||||
areaManager ();
|
||||
void addArea(area *newArea) {areas.add(newArea);}
|
||||
void removeArea(area *oldArea) {areas.remove(oldArea); }
|
||||
void freeArea(int area);
|
||||
void freeArea(area_id area);
|
||||
team_id getTeam(void) {return team;}
|
||||
unsigned long getNextAddress(int pages,unsigned long minimum=USER_BASE);
|
||||
area *findArea(void *address);
|
||||
@@ -91,10 +91,10 @@ class areaManager // One of these per process
|
||||
{
|
||||
static long lockCount=0;
|
||||
if (!((lockCount++)%200))
|
||||
printf ("locking\n");
|
||||
error ("locking\n");
|
||||
acquire_sem(myLock);
|
||||
}
|
||||
void unlock() {/*printf ("unlocking\n");*/release_sem(myLock);}
|
||||
void unlock() {/*error ("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)
|
||||
{
|
||||
|
||||
@@ -11,25 +11,25 @@ area *poolarea::get(void)
|
||||
area *ret=NULL;
|
||||
if (unused.count())
|
||||
{
|
||||
//printf ("poolarea::get: Getting an unused one!\n");
|
||||
//error ("poolarea::get: Getting an unused one!\n");
|
||||
acquire_sem(inUse);
|
||||
ret=(area *)unused.next();
|
||||
release_sem(inUse);
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
//printf ("poolarea::get: Returning address:%x \n",ret);
|
||||
//error ("poolarea::get: Returning address:%x \n",ret);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf ("poolarea::get: Getting a new page!\n");
|
||||
//error ("poolarea::get: Getting a new page!\n");
|
||||
page *newPage=vmBlock->pageMan->getPage();
|
||||
if (!newPage)
|
||||
throw ("Out of pages to allocate a pool!");
|
||||
int newCount=PAGE_SIZE/sizeof(area);
|
||||
acquire_sem(inUse);
|
||||
//printf ("poolarea::get: Adding %d new elements to the pool!\n",newCount);
|
||||
//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);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <OS.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static sem_id errorPrinting=0;
|
||||
|
||||
void error(char *fmt, ...)
|
||||
{
|
||||
if (errorPrinting==0)
|
||||
errorPrinting=create_sem(1,"error_printing");
|
||||
acquire_sem(errorPrinting);
|
||||
va_list argp;
|
||||
char tmp[1000];
|
||||
sprintf(tmp, "[%lld] error: %s",real_time_clock_usecs(),fmt);
|
||||
va_start(argp, tmp);
|
||||
vfprintf(stderr,tmp,argp);
|
||||
va_end(argp);
|
||||
release_sem(errorPrinting);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
void error(char *fmt, ...);
|
||||
@@ -3,6 +3,7 @@
|
||||
// Simple linked list
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "error.h"
|
||||
|
||||
struct node
|
||||
{
|
||||
@@ -18,7 +19,7 @@ class list {
|
||||
rock=newNode;
|
||||
nodeCount++;
|
||||
}
|
||||
//int count(void) {printf ("list::count: About to return %d\n",nodeCount);return nodeCount;}
|
||||
//int count(void) {error ("list::count: About to return %d\n",nodeCount);return nodeCount;}
|
||||
int count(void) {return nodeCount;}
|
||||
node *next(void)
|
||||
{
|
||||
@@ -34,7 +35,7 @@ class list {
|
||||
}
|
||||
void remove(node *toNuke)
|
||||
{
|
||||
//printf ("list::remove starting: nuking %x \n",toNuke);
|
||||
//error ("list::remove starting: nuking %x \n",toNuke);
|
||||
//dump();
|
||||
if (rock==toNuke)
|
||||
{
|
||||
@@ -52,14 +53,14 @@ class list {
|
||||
done=true;
|
||||
}
|
||||
}
|
||||
//printf ("list::remove ending: \n");
|
||||
//error ("list::remove ending: \n");
|
||||
//dump();
|
||||
}
|
||||
void dump(void)
|
||||
{
|
||||
for (struct node *cur=rock;cur;cur=cur->next)
|
||||
{
|
||||
printf ("list::dump: At %p, next = %p\n",cur,cur->next);
|
||||
error ("list::dump: At %p, next = %p\n",cur,cur->next);
|
||||
}
|
||||
}
|
||||
struct node *rock;
|
||||
|
||||
@@ -32,7 +32,7 @@ int main(int argc,char **argv)
|
||||
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 ("Failure on adding with no isLessThan, printf = %s\n", badness);
|
||||
printf ("Success on adding with no isLessThan, \n" );
|
||||
}
|
||||
catch(...)
|
||||
|
||||
@@ -17,27 +17,27 @@ class orderedList : public list
|
||||
void add(node *in)
|
||||
{
|
||||
nodeCount++;
|
||||
//printf ("orderedList::add starting\n");
|
||||
//error ("orderedList::add starting\n");
|
||||
if (!rock || isLessThan(in,rock))
|
||||
{ // special case - this will be the first one
|
||||
//printf ("orderedList::specialCase starting\n");
|
||||
//error ("orderedList::specialCase starting\n");
|
||||
in->next=rock;
|
||||
rock=in;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf ("orderedList::Normal Case starting\n");
|
||||
//error ("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");
|
||||
//error ("orderedList::Normal Case Adding Start\n");
|
||||
in->next=cur->next;
|
||||
cur->next=in;
|
||||
done=true;
|
||||
//printf ("orderedList::Normal Case Adding END\n");
|
||||
//error ("orderedList::Normal Case Adding END\n");
|
||||
}
|
||||
//printf ("orderedList::Normal Case ending\n");
|
||||
//error ("orderedList::Normal Case ending\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "page.h"
|
||||
#include "string.h"
|
||||
|
||||
void page::zero(void)
|
||||
{
|
||||
for (int i=0;i<(PAGE_SIZE/4);i++)
|
||||
((long *)physicalAddress)[i]=0;
|
||||
memset(physicalAddress,'0',PAGE_SIZE);
|
||||
// for (int i=0;i<(PAGE_SIZE/4);i++)
|
||||
// ((long *)physicalAddress)[i]=0;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ class page : public node {
|
||||
void setup (void *address) {count=0;physicalAddress=address;};
|
||||
void zero(void);
|
||||
unsigned long getAddress(void) {return (unsigned long)physicalAddress;}
|
||||
void dump(void) { printf ("Page %p, physicalAddress = %lx\n",this,getAddress()); }
|
||||
void dump(void) { error ("page::dump: Page %p, physicalAddress = %lx\n",this,getAddress()); }
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -19,8 +19,8 @@ void pageManager::setup(void *area,int pages)
|
||||
{
|
||||
page *newPage=(page *)(addOffset(area,i*sizeof(page)));
|
||||
newPage->setup(addOffset(area,(i+pageOverhead)*PAGE_SIZE));
|
||||
//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);
|
||||
//error ("newPage = %x, setup = %x\n",newPage,addOffset(area,(i+pageOverhead)*PAGE_SIZE));
|
||||
//error ("i = %d, sizeof(page) = %x, pageOverhead = %d\n",i,sizeof(page),pageOverhead);
|
||||
//newPage->dump();
|
||||
unused.add(newPage);
|
||||
}
|
||||
@@ -30,9 +30,9 @@ void pageManager::setup(void *area,int pages)
|
||||
inUseLock=create_sem (1,"inuse_lock");
|
||||
totalPages=pages;
|
||||
/*
|
||||
printf ("pageManager::pageManager: About to dump the clean pages (should be 0):\n\n");
|
||||
error ("pageManager::pageManager: About to dump the clean pages (should be 0):\n\n");
|
||||
clean.dump();
|
||||
printf ("pageManager::pageManager: About to dump the unused pages (should not be 0):\n\n");
|
||||
error ("pageManager::pageManager: About to dump the unused pages (should not be 0):\n\n");
|
||||
unused.dump();
|
||||
*/
|
||||
}
|
||||
@@ -40,44 +40,44 @@ void pageManager::setup(void *area,int pages)
|
||||
page *pageManager::getPage(void)
|
||||
{
|
||||
page *ret=NULL;
|
||||
// printf ("pageManager::getPage: Checking clean\n");
|
||||
//printf ("pageManager::getPage:cleanCount = %d\n", clean.nodeCount);
|
||||
if (clean.count())
|
||||
// error ("pageManager::getPage: Checking clean\n");
|
||||
//error ("pageManager::getPage:cleanCount = %d\n", clean.nodeCount);
|
||||
while (!ret)
|
||||
{
|
||||
//printf ("pageManager::getPage:locking clean\n");
|
||||
acquire_sem(cleanLock);
|
||||
//printf ("pageManager::getPage:locked clean\n");
|
||||
ret=(page *)clean.next();
|
||||
//printf ("pageManager::getPage:got next clean\n");
|
||||
release_sem(cleanLock);
|
||||
//printf ("pageManager::getPage:unlocked clean\n");
|
||||
} // This could fail if someone swooped in and stole our page.
|
||||
else if (unused.count())
|
||||
{
|
||||
//printf ("pageManager::getPage:Checking unused\n");
|
||||
acquire_sem(unusedLock);
|
||||
ret=(page *)unused.next();
|
||||
//printf ("pageManager::getPage:got next unused\n");
|
||||
release_sem(unusedLock);
|
||||
//printf ("pageManager::getPage:next unused = %x\n",ret);
|
||||
if (ret)
|
||||
ret->zero();
|
||||
} // This could fail if someone swooped in and stole our page.
|
||||
if (ret)
|
||||
{
|
||||
acquire_sem(inUseLock);
|
||||
inUse.add(ret);
|
||||
release_sem(inUseLock);
|
||||
ret->count++;
|
||||
if (clean.count())
|
||||
{
|
||||
//error ("pageManager::getPage:locking clean\n");
|
||||
acquire_sem(cleanLock);
|
||||
//error ("pageManager::getPage:locked clean\n");
|
||||
ret=(page *)clean.next();
|
||||
//error ("pageManager::getPage:got next clean\n");
|
||||
release_sem(cleanLock);
|
||||
//error ("pageManager::getPage:unlocked clean\n");
|
||||
} // This could fail if someone swooped in and stole our page.
|
||||
else if (unused.count())
|
||||
{
|
||||
//error ("pageManager::getPage:Checking unused\n");
|
||||
acquire_sem(unusedLock);
|
||||
ret=(page *)unused.next();
|
||||
//error ("pageManager::getPage:got next unused\n");
|
||||
release_sem(unusedLock);
|
||||
//error ("pageManager::getPage:next unused = %x\n",ret);
|
||||
if (ret)
|
||||
ret->zero();
|
||||
} // This could fail if someone swooped in and stole our page.
|
||||
}
|
||||
// printf ("pageManager::getPage:leaving with page = %x\n", ret->getAddress());
|
||||
acquire_sem(inUseLock);
|
||||
inUse.add(ret);
|
||||
release_sem(inUseLock);
|
||||
ret->count++;
|
||||
// error ("pageManager::getPage:leaving with page = %x\n", ret->getAddress());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pageManager::freePage(page *toFree)
|
||||
{
|
||||
// printf ("Inside freePage; old value = %d",toFree->count);
|
||||
if (atomic_add(&(toFree->count),-1)==0)
|
||||
error ("Inside freePage; old value = %d",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);
|
||||
inUse.remove(toFree);
|
||||
@@ -86,7 +86,7 @@ void pageManager::freePage(page *toFree)
|
||||
unused.add(toFree);
|
||||
release_sem(unusedLock);
|
||||
}
|
||||
// printf (" new value = %d, page = %x\n",toFree->count,toFree->getAddress());
|
||||
error (" new value = %d, page = %x\n",toFree->count,toFree->getAddress());
|
||||
}
|
||||
|
||||
void pageManager::cleaner(void)
|
||||
@@ -95,7 +95,7 @@ void pageManager::cleaner(void)
|
||||
{
|
||||
if (unused.count())
|
||||
{
|
||||
//printf ("pageManager::cleaner: About to vacuum a page\n");
|
||||
//error ("pageManager::cleaner: About to vacuum a page\n");
|
||||
acquire_sem(unusedLock);
|
||||
page *first=(page *)unused.next();
|
||||
release_sem(unusedLock);
|
||||
@@ -103,7 +103,7 @@ void pageManager::cleaner(void)
|
||||
acquire_sem(cleanLock);
|
||||
clean.add(first);
|
||||
release_sem(cleanLock);
|
||||
//printf ("pageManager::cleaner: All done with vacuum a page\n");
|
||||
//error ("pageManager::cleaner: All done with vacuum a page\n");
|
||||
snooze(125000);
|
||||
}
|
||||
}
|
||||
@@ -118,21 +118,21 @@ int pageManager::desperation(void)
|
||||
|
||||
void pageManager::dump(void)
|
||||
{
|
||||
printf ("Dumping the unused list\n");
|
||||
error ("Dumping the unused list\n");
|
||||
for (struct node *cur=unused.rock;cur;)
|
||||
{
|
||||
page *thisPage=(page *)cur;
|
||||
thisPage->dump();
|
||||
cur=cur->next;
|
||||
}
|
||||
printf ("Dumping the clean list\n");
|
||||
error ("Dumping the clean list\n");
|
||||
for (struct node *cur=clean.rock;cur;)
|
||||
{
|
||||
page *thisPage=(page *)cur;
|
||||
thisPage->dump();
|
||||
cur=cur->next;
|
||||
}
|
||||
printf ("Dumping the inuse list\n");
|
||||
error ("Dumping the inuse list\n");
|
||||
for (struct node *cur=inUse.rock;cur;)
|
||||
{
|
||||
page *thisPage=(page *)cur;
|
||||
|
||||
@@ -21,25 +21,25 @@ class poolTYPE
|
||||
TYPE *ret=NULL;
|
||||
if (unused.count())
|
||||
{
|
||||
printf ("poolTYPE::get: Getting an unused one!\n");
|
||||
error ("poolTYPE::get: Getting an unused one!\n");
|
||||
acquire_sem(inUse);
|
||||
ret=(TYPE *)unused.next();
|
||||
release_sem(inUse);
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
printf ("poolTYPE::get: Returning address:%x \n",ret);
|
||||
error ("poolTYPE::get: Returning address:%x \n",ret);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("poolTYPE::get: Getting a new page!\n");
|
||||
error ("poolTYPE::get: Getting a new page!\n");
|
||||
page *newPage=vmBlock->pageMan->getPage();
|
||||
if (!newPage)
|
||||
throw ("Out of pages to allocate a pool!");
|
||||
int newCount=PAGE_SIZE/sizeof(TYPE);
|
||||
acquire_sem(inUse);
|
||||
printf ("poolTYPE::get: Adding %d new elements to the pool!\n",newCount);
|
||||
error ("poolTYPE::get: Adding %d new elements to the pool!\n",newCount);
|
||||
for (int i=0;i<newCount;i++)
|
||||
unused.add(((void *)(newPage->getAddress()+(i*sizeof(TYPE)))));
|
||||
release_sem(inUse);
|
||||
|
||||
@@ -12,53 +12,52 @@ swapFileManager::swapFileManager(void)
|
||||
{
|
||||
swapFile = open("/boot/var/tmp/OBOS_swap",O_RDWR|O_CREAT,0x777 );
|
||||
if (swapFile==-1)
|
||||
printf ("swapfileManager::swapFileManger: swapfile not opened, errno = %ul, %s\n",errno,strerror(errno));
|
||||
error ("swapfileManager::swapFileManger: swapfile not opened, errno = %ul, %s\n",errno,strerror(errno));
|
||||
lockFreeList=create_sem(1,"SwapFile Free List Semaphore"); // Should have team name in it.
|
||||
}
|
||||
|
||||
void swapFileManager::write_block(vnode &node,void *loc,unsigned long size)
|
||||
{
|
||||
//printf ("swapFileManager::write_block: writing, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc);
|
||||
//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))
|
||||
printf ("seek failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno));
|
||||
error ("seek failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno));
|
||||
if (-1==write(node.fd,loc,size))
|
||||
printf ("Write failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno));
|
||||
error ("Write failed, fd = %d, errno = %d, %s\n",node.fd,errno,strerror(errno));
|
||||
node.valid=true;
|
||||
//printf ("swapFileManager::write_block: done, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc);
|
||||
//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...
|
||||
//printf ("swapFileManager::read_block: reading, node.fd = %d, node.offset = %d into %x\n",node.fd, node.offset,loc);
|
||||
//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)
|
||||
{
|
||||
//printf ("swapFileManager::findNode: Entering findNode \n");
|
||||
//error ("swapFileManager::findNode: Entering findNode \n");
|
||||
//swapFileFreeList.dump();
|
||||
//printf ("swapFileManager::findNode: Finding a new node for you, Master: ");
|
||||
//error ("swapFileManager::findNode: Finding a new node for you, Master: ");
|
||||
vnode *newNode;
|
||||
//printf ("locking in sfm\n");
|
||||
//error ("locking in sfm\n");
|
||||
Lock();
|
||||
newNode=reinterpret_cast<vnode *>(swapFileFreeList.next());
|
||||
//printf ("unlocking in sfm\n");
|
||||
//error ("unlocking in sfm\n");
|
||||
Unlock();
|
||||
if (!newNode)
|
||||
{
|
||||
newNode=new (vmBlock->vnodePool->get()) vnode;
|
||||
newNode->fd=swapFile;
|
||||
newNode->offset=maxNode+=PAGE_SIZE;
|
||||
//printf (" New One: %d\n",newNode->offset);
|
||||
//error (" New One: %d\n",newNode->offset);
|
||||
}
|
||||
newNode->valid=false;
|
||||
newNode->count=0;
|
||||
//printf ("swapFileManager::findNode: swapFileFreeList is now: ");
|
||||
newNode->count=1;
|
||||
//error ("swapFileManager::findNode: swapFileFreeList is now: ");
|
||||
//swapFileFreeList.dump();
|
||||
newNode->count++;
|
||||
return *newNode;
|
||||
}
|
||||
|
||||
@@ -67,12 +66,12 @@ void swapFileManager::freeVNode(vnode &v)
|
||||
v.count--;
|
||||
if (v.count==0)
|
||||
{
|
||||
//printf ("locking in sfm\n");
|
||||
//error ("locking in sfm\n");
|
||||
Lock();
|
||||
//printf ("swapFileManager::freeNode: Starting Freeing a new node for you, Master: offset:%d\n",v.offset);
|
||||
//error ("swapFileManager::freeNode: Starting Freeing a new node for you, Master: offset:%d\n",v.offset);
|
||||
v.valid=false;
|
||||
swapFileFreeList.add(&v);
|
||||
//printf ("unlocking in sfm\n");
|
||||
//error ("unlocking in sfm\n");
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
+60
-43
@@ -6,6 +6,7 @@
|
||||
#include <string.h>
|
||||
|
||||
vmInterface vm(30);
|
||||
thread_id loop1,loop2,loop3,info1,mmap1,clone1;
|
||||
|
||||
void writeByte(unsigned long addr,unsigned int offset, char value) { vm.setByte(addr+offset,value); }
|
||||
|
||||
@@ -16,29 +17,45 @@ int createFillAndTest(int pages,char *name)
|
||||
try{
|
||||
unsigned long addr;
|
||||
int area1;
|
||||
printf ("%s: createFillAndTest: about to create \n",name);
|
||||
error ("%s: createFillAndTest: about to create \n",name);
|
||||
area1=vm.createArea("Mine",pages,(void **)(&addr));
|
||||
printf ("%s: createFillAndTest: create done\n",name);
|
||||
error ("%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);
|
||||
if (!(i%9024) )
|
||||
error ("Writing to byte %d of area %s\n",i,name);
|
||||
writeByte(addr,i,i%256);
|
||||
}
|
||||
printf ("%s: createFillAndTest: writing done\n",name);
|
||||
error ("%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%9024) )
|
||||
error ("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));
|
||||
error ("ERROR! Byte at offset %d does not match: expected: %d, found: %d\n",i,i%256,readByte(addr,i));
|
||||
}
|
||||
printf ("%s: createFillAndTest: reading done\n",name);
|
||||
error ("%s: createFillAndTest: reading done\n",name);
|
||||
return area1;
|
||||
}
|
||||
catch (const char *t)
|
||||
{
|
||||
vm.suspendAll();
|
||||
thread_id me=find_thread(NULL);
|
||||
suspend_thread(clone1);
|
||||
suspend_thread(mmap1);
|
||||
suspend_thread(info1);
|
||||
if (loop1!=me)
|
||||
suspend_thread(loop1);
|
||||
if (loop2!=me)
|
||||
suspend_thread(loop2);
|
||||
if (loop3!=me)
|
||||
suspend_thread(loop3);
|
||||
debugger(t);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf ("Exception thrown!\n");
|
||||
error ("Exception thrown!\n");
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -54,17 +71,17 @@ struct loopTestParameters
|
||||
|
||||
int32 loopTest(void *parameters)
|
||||
{
|
||||
printf ("Starting Loop Test!\n");
|
||||
error ("Starting Loop Test!\n");
|
||||
loopTestParameters *params=((loopTestParameters *)parameters);
|
||||
int area1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
snooze(params->initialSnooze);
|
||||
printf ("Creating %s area\n",params->name);
|
||||
error ("Creating %s area\n",params->name);
|
||||
area1=createFillAndTest(params->areaSize,params->name);
|
||||
snooze(params->holdSnooze);
|
||||
printf ("Freeing %s area\n",params->name);
|
||||
error ("Freeing %s area\n",params->name);
|
||||
vm.freeArea(area1);
|
||||
snooze(params->loopSnooze);
|
||||
}
|
||||
@@ -79,23 +96,23 @@ int32 getInfoTest(void *parameters)
|
||||
while (1)
|
||||
{
|
||||
snooze(params->initialSnooze);
|
||||
//printf ("Creating %s area\n",params->name);
|
||||
//error ("Creating %s area\n",params->name);
|
||||
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 : %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);
|
||||
error ("Area info : \n");
|
||||
error ("name : %s\n",ai.name);
|
||||
error ("size : %ld\n",ai.size);
|
||||
error ("lock : %ld\n",ai.lock);
|
||||
error ("team : %ld\n",ai.team);
|
||||
error ("ram_size : %ld\n",ai.ram_size);
|
||||
error ("in_count : %ld\n",ai.in_count);
|
||||
error ("out_count : %ld\n",ai.out_count);
|
||||
error ("copy_count : %ld\n",ai.copy_count);
|
||||
error ("address : %p\n",ai.address);
|
||||
|
||||
printf ("Freeing %s area\n",params->name);
|
||||
error ("Freeing %s area\n",params->name);
|
||||
vm.freeArea(area1);
|
||||
snooze(params->loopSnooze);
|
||||
}
|
||||
@@ -109,23 +126,23 @@ int32 mmapTest (void *parameters)
|
||||
while (1)
|
||||
{
|
||||
int fd = open ("OBOS_mmap",O_RDWR|O_CREAT,0x777);
|
||||
printf ("Opened file, fd = %d\n",fd);
|
||||
error ("Opened file, fd = %d\n",fd);
|
||||
snooze(params->initialSnooze);
|
||||
printf ("Creating %s mmap\n",params->name);
|
||||
error ("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 = %p\n",map);
|
||||
error ("mmap address = %p\n",map);
|
||||
for (int i=0;i<size;i++)
|
||||
writeByte((int32)map,i,i%256);
|
||||
printf ("mmapTest: writing done\n");
|
||||
error ("mmapTest: writing done\n");
|
||||
for (int i=0;i<size;i++)
|
||||
if (i%256!=readByte((int32)map,i))
|
||||
printf ("ERROR! Byte at offset %d does not match: expected: %d, found: %d\n",i,i%256,readByte((int32)map,i));
|
||||
printf ("mmapTest: reading done\n");
|
||||
error ("ERROR! Byte at offset %d does not match: expected: %d, found: %d\n",i,i%256,readByte((int32)map,i));
|
||||
error ("mmapTest: reading done\n");
|
||||
snooze(params->loopSnooze);
|
||||
vm.munmap(map,size);
|
||||
close(fd);
|
||||
printf ("Closed file, fd = %d\n",fd);
|
||||
error ("Closed file, fd = %d\n",fd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,16 +155,16 @@ int32 cloneTest (void *parameters)
|
||||
while (1)
|
||||
{
|
||||
snooze(params->initialSnooze);
|
||||
// printf ("Creating %s area, size = %d\n",params->name,params->areaSize);
|
||||
// error ("Creating %s area, size = %d\n",params->name,params->areaSize);
|
||||
area1=createFillAndTest(params->areaSize,params->name);
|
||||
// printf ("cloning, create done \n");
|
||||
// error ("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 %p does not match: expected: %d, found: %d\n",i,cloneAddr,i%256,readByte((int32)cloneAddr,i));
|
||||
// printf ("Snoozing, compare done \n");
|
||||
error ("ERROR! Clone Byte at offset %d of %p does not match: expected: %d, found: %d\n",i,cloneAddr,i%256,readByte((int32)cloneAddr,i));
|
||||
// error ("Snoozing, compare done \n");
|
||||
snooze(params->holdSnooze);
|
||||
// printf ("Freeing %s area\n",params->name);
|
||||
// error ("Freeing %s area\n",params->name);
|
||||
vm.freeArea(area2);
|
||||
vm.freeArea(area1);
|
||||
snooze(params->loopSnooze);
|
||||
@@ -163,12 +180,12 @@ int main(int argc,char **argv)
|
||||
loopTestParameters mmap1Params={"mmap",500000,8192,400000,1000000};
|
||||
loopTestParameters clone1Params={"clone1",200000,2,300000,400000};
|
||||
|
||||
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(loop1=spawn_thread(loopTest,"area test 1",0,&area1Params));
|
||||
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));
|
||||
|
||||
snooze(1000000000);
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ struct vnode : public node
|
||||
int fd;
|
||||
unsigned long offset;
|
||||
bool valid;
|
||||
int count;
|
||||
long count;
|
||||
|
||||
vnode (void)
|
||||
{
|
||||
|
||||
@@ -70,18 +70,18 @@ vmInterface::vmInterface(int pages)
|
||||
// This is compatability for in BeOS usage only...
|
||||
if (0>=create_area("vm_test",(void **)(&vmBlock),B_ANY_ADDRESS,B_PAGE_SIZE*pages,B_NO_LOCK,B_READ_AREA|B_WRITE_AREA))
|
||||
{
|
||||
printf ("pageManager::pageManager: No memory!\n");
|
||||
error ("pageManager::pageManager: No memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
//printf ("Allocated an area. Address = %x\n",vmBlock);
|
||||
//error ("Allocated an area. Address = %x\n",vmBlock);
|
||||
// Figure out how many pages we need
|
||||
int pageCount = (sizeof(poolarea)+sizeof(poolvpage)+sizeof(poolvnode)+sizeof(pageManager)+sizeof(swapFileManager)+sizeof(cacheManager)+sizeof(vmHeaderBlock)+PAGE_SIZE-1)/PAGE_SIZE;
|
||||
if (pageCount >=pages)
|
||||
{
|
||||
printf ("Hey! Go buy some ram! Trying to create a VM with fewer pages than the setup will take!\n");
|
||||
error ("Hey! Go buy some ram! Trying to create a VM with fewer pages than the setup will take!\n");
|
||||
exit(1);
|
||||
}
|
||||
//printf ("Need %d pages, creation calls for %d\n",pageCount,pages);
|
||||
//error ("Need %d pages, creation calls for %d\n",pageCount,pages);
|
||||
void *currentAddress = addToPointer(vmBlock,sizeof(struct vmHeaderBlock));
|
||||
vmBlock->areaPool = new (currentAddress) poolarea;
|
||||
currentAddress=addToPointer(currentAddress,sizeof(poolarea));
|
||||
@@ -95,14 +95,14 @@ vmInterface::vmInterface(int pages)
|
||||
currentAddress=addToPointer(currentAddress,sizeof(swapFileManager));
|
||||
vmBlock->cacheMan = new (currentAddress) cacheManager;
|
||||
currentAddress=addToPointer(currentAddress,sizeof(cacheManager));
|
||||
//printf ("Need %d pages, creation calls for %d\n",pageCount,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);
|
||||
//error ("Need %d pages, creation calls for %d\n",pageCount,pages);
|
||||
//error ("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);
|
||||
}
|
||||
|
||||
resume_thread(spawn_thread(cleanerThread,"cleanerThread",0,(vmBlock->pageMan)));
|
||||
resume_thread(spawn_thread(saverThread,"saverThread",0,getAM()));
|
||||
resume_thread(spawn_thread(pagerThread,"pagerThread",0,getAM()));
|
||||
resume_thread(tid_cleaner=spawn_thread(cleanerThread,"cleanerThread",0,(vmBlock->pageMan)));
|
||||
resume_thread(tid_saver=spawn_thread(saverThread,"saverThread",0,getAM()));
|
||||
resume_thread(tid_pager=spawn_thread(pagerThread,"pagerThread",0,getAM()));
|
||||
}
|
||||
|
||||
int vmInterface::getAreaByAddress(void *address)
|
||||
@@ -210,3 +210,10 @@ status_t vmInterface::munmap(void *addr, size_t len)
|
||||
retVal = getAM()->munmap(addr,len);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void vmInterface::suspendAll(void)
|
||||
{
|
||||
suspend_thread(tid_cleaner);
|
||||
suspend_thread(tid_saver);
|
||||
suspend_thread(tid_pager);
|
||||
}
|
||||
|
||||
@@ -33,4 +33,6 @@ class vmInterface // This is the class that "owns" all of the managers.
|
||||
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
|
||||
void setInt(unsigned long offset,int value) {getAM()->setByte(offset,value);} // This is for testing only
|
||||
};
|
||||
void suspendAll(void);
|
||||
thread_id tid_cleaner,tid_saver,tid_pager;
|
||||
};
|
||||
|
||||
@@ -9,25 +9,25 @@ vnode *poolvnode::get(void)
|
||||
vnode *ret=NULL;
|
||||
if (unused.count())
|
||||
{
|
||||
//printf ("poolvnode::get: Getting an unused one!\n");
|
||||
//error ("poolvnode::get: Getting an unused one!\n");
|
||||
acquire_sem(inUse);
|
||||
ret=(vnode *)unused.next();
|
||||
release_sem(inUse);
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
//printf ("poolvnode::get: Returning address:%x \n",ret);
|
||||
//error ("poolvnode::get: Returning address:%x \n",ret);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf ("poolvnode::get: Getting a new page!\n");
|
||||
//error ("poolvnode::get: Getting a new page!\n");
|
||||
page *newPage=vmBlock->pageMan->getPage();
|
||||
if (!newPage)
|
||||
throw ("Out of pages to allocate a pool!");
|
||||
int newCount=PAGE_SIZE/sizeof(vnode);
|
||||
acquire_sem(inUse);
|
||||
//printf ("poolvnode::get: Adding %d new elements to the pool!\n",newCount);
|
||||
//error ("poolvnode::get: Adding %d new elements to the pool!\n",newCount);
|
||||
for (int i=0;i<newCount;i++)
|
||||
unused.add(((node *)(newPage->getAddress()+(i*sizeof(vnode)))));
|
||||
release_sem(inUse);
|
||||
|
||||
+23
-22
@@ -29,7 +29,7 @@ vpage::vpage(void)
|
||||
// backing and/or physMem can be NULL/0.
|
||||
void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state)
|
||||
{
|
||||
//printf ("vpage::vpage: start = %x, vnode.fd=%d, vnode.offset=%d, physMem = %x\n",start,((backing)?backing->fd:0),((backing)?backing->offset:0), ((physMem)?(physMem->getAddress()):0));
|
||||
//error ("vpage::vpage: start = %x, vnode.fd=%d, vnode.offset=%d, physMem = %x\n",start,((backing)?backing->fd:0),((backing)?backing->offset:0), ((physMem)?(physMem->getAddress()):0));
|
||||
start_address=start;
|
||||
end_address=start+PAGE_SIZE-1;
|
||||
protection=prot;
|
||||
@@ -38,7 +38,7 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
|
||||
if (backing)
|
||||
{
|
||||
backingNode=backing;
|
||||
backing->count++;
|
||||
atomic_add(&(backing->count),1);
|
||||
}
|
||||
else
|
||||
backingNode=&(vmBlock->swapMan->findNode());
|
||||
@@ -47,11 +47,11 @@ void vpage::setup(unsigned long start,vnode *backing, page *physMem,protectType
|
||||
else
|
||||
{
|
||||
if (physMem)
|
||||
physMem->count++;
|
||||
atomic_add(&(physMem->count),1);
|
||||
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));
|
||||
//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));
|
||||
}
|
||||
|
||||
void vpage::cleanup(void)
|
||||
@@ -74,12 +74,12 @@ 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 = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
|
||||
error ("vpage::fault: virtual address = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
|
||||
if (writeError)
|
||||
{
|
||||
dirty=true;
|
||||
if (physPage)
|
||||
{
|
||||
dirty=true;
|
||||
if (protection==copyOnWrite) // Else, this was just a "let me know when I am dirty"...
|
||||
{
|
||||
page *newPhysPage=vmBlock->pageMan->getPage();
|
||||
@@ -97,44 +97,45 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa
|
||||
physPage=vmBlock->pageMan->getPage();
|
||||
if (!physPage) // No room at the inn
|
||||
return false;
|
||||
// printf ("vpage::fault: New page allocated! new physical address = %x vnode.fd=%d, vnode.offset=%d, \n",physPage->getAddress(),((backingNode)?backingNode->fd:0),((backingNode)?backingNode->offset:0));
|
||||
error ("vpage::fault: New page allocated! new physical address = %x vnode.fd=%d, vnode.offset=%d, \n",physPage->getAddress(),((backingNode)?backingNode->fd:0),((backingNode)?backingNode->offset:0));
|
||||
// Update the architecture specific stuff here...
|
||||
// This refresh is unneeded if the data was never written out...
|
||||
// dump();
|
||||
dump();
|
||||
refresh(); // I wonder if these vnode calls are safe during an interrupt...
|
||||
// printf ("vpage::fault: Refreshed\n");
|
||||
// dump();
|
||||
// printf ("vpage::fault: exiting\n");
|
||||
dirty=true;
|
||||
error ("vpage::fault: Refreshed\n");
|
||||
dump();
|
||||
error ("vpage::fault: exiting\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
char vpage::getByte(unsigned long address,areaManager *manager)
|
||||
{
|
||||
//printf ("vpage::getByte: address = %ld\n",address );
|
||||
//error ("vpage::getByte: address = %ld\n",address );
|
||||
if (!physPage)
|
||||
if (!manager->fault((void *)(address),false))
|
||||
throw ("vpage::getByte");
|
||||
//printf ("vpage::getByte: About to return %d\n", *((char *)(address-start_address+physPage->getAddress())));
|
||||
//error ("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,areaManager *manager)
|
||||
{
|
||||
// printf ("vpage::setByte: address = %d, value = %d\n",address, value);
|
||||
// error ("vpage::setByte: address = %d, value = %d\n",address, value);
|
||||
if (!physPage)
|
||||
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())));
|
||||
// error ("vpage::setByte: physical address = %d, value = %d\n",physPage->getAddress(), *((char *)(physPage->getAddress())));
|
||||
}
|
||||
|
||||
int vpage::getInt(unsigned long address,areaManager *manager)
|
||||
{
|
||||
printf ("vpage::getInt: address = %ld\n",address );
|
||||
error ("vpage::getInt: address = %ld\n",address );
|
||||
if (!physPage)
|
||||
if (!manager->fault((void *)(address),false))
|
||||
throw ("vpage::getInt");
|
||||
printf ("vpage::getInt: About to return %d\n", *((char *)(address-start_address+physPage->getAddress())));
|
||||
error ("vpage::getInt: About to return %d\n", *((char *)(address-start_address+physPage->getAddress())));
|
||||
dump();
|
||||
return *((int *)(address-start_address+physPage->getAddress()));
|
||||
}
|
||||
@@ -149,10 +150,10 @@ void vpage::setInt(unsigned long address,int value,areaManager *manager)
|
||||
|
||||
void vpage::pager(int desperation)
|
||||
{
|
||||
//printf ("vpage::pager start desperation = %d\n",desperation);
|
||||
//error ("vpage::pager start desperation = %d\n",desperation);
|
||||
if (!swappable)
|
||||
return;
|
||||
printf ("vpage::pager swappable\n");
|
||||
error ("vpage::pager swappable\n");
|
||||
switch (desperation)
|
||||
{
|
||||
case 1: return; break;
|
||||
@@ -162,11 +163,11 @@ void vpage::pager(int desperation)
|
||||
case 5: if (!physPage) return;break;
|
||||
default: return;break;
|
||||
}
|
||||
printf ("vpage::pager flushing\n");
|
||||
error ("vpage::pager flushing\n");
|
||||
flush();
|
||||
printf ("vpage::pager freeing\n");
|
||||
error ("vpage::pager freeing\n");
|
||||
vmBlock->pageMan->freePage(physPage);
|
||||
printf ("vpage::pager going to NULL\n");
|
||||
error ("vpage::pager going to NULL\n");
|
||||
physPage=NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,11 +36,11 @@ class vpage : public node
|
||||
|
||||
void dump(void)
|
||||
{
|
||||
printf ("Dumping vpage %p, address = %lx, \n\t physPage: ",this,start_address);
|
||||
error ("Dumping vpage %p, address = %lx, physPage: \n",this,start_address);
|
||||
if (physPage)
|
||||
physPage->dump();
|
||||
else
|
||||
printf ("NULL\n");
|
||||
error ("NULL\n");
|
||||
}
|
||||
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
|
||||
|
||||
@@ -10,25 +10,25 @@ vpage *poolvpage::get(void)
|
||||
vpage *ret=NULL;
|
||||
if (unused.count())
|
||||
{
|
||||
//printf ("poolvpage::get: Getting an unused one!\n");
|
||||
//error ("poolvpage::get: Getting an unused one!\n");
|
||||
acquire_sem(inUse);
|
||||
ret=(vpage *)unused.next();
|
||||
release_sem(inUse);
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
//printf ("poolvpage::get: Returning address:%x \n",ret);
|
||||
//error ("poolvpage::get: Returning address:%x \n",ret);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf ("poolvpage::get: Getting a new page!\n");
|
||||
//error ("poolvpage::get: Getting a new page!\n");
|
||||
page *newPage=vmBlock->pageMan->getPage();
|
||||
if (!newPage)
|
||||
throw ("Out of pages to allocate a pool!");
|
||||
int newCount=PAGE_SIZE/sizeof(vpage);
|
||||
acquire_sem(inUse);
|
||||
//printf ("poolvpage::get: Adding %d new elements to the pool!\n",newCount);
|
||||
//error ("poolvpage::get: Adding %d new elements to the pool!\n",newCount);
|
||||
for (int i=0;i<newCount;i++)
|
||||
unused.add(((node *)(newPage->getAddress()+(i*sizeof(vpage)))));
|
||||
release_sem(inUse);
|
||||
|
||||
Reference in New Issue
Block a user