Updates to make creating areas and accessing bytes work. Lots of debugging

printfs, etc in here. But some bug fixes and better code.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@426 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Phipps 2002-07-25 01:27:00 +00:00
parent d10f93e702
commit 72515139f7
14 changed files with 103 additions and 32 deletions

View File

@ -9,6 +9,7 @@ area::area (areaManager *myManager)
unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long requested,int pageCount)
{
// We will lock in the callers
unsigned long base;
switch (type)
{
@ -33,6 +34,7 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque
status_t area::createAreaMappingFile(char *name, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset)
{
manager->lock();
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
vpage *newPage;
@ -45,36 +47,51 @@ status_t area::createAreaMappingFile(char *name, int pageCount,void **address, a
vpages.add(newPage);
}
state=inState;
start_address=base;
end_address=base+pageCount*PAGE_SIZE;
manager->unlock();
}
status_t area::createArea(char *name, int pageCount,void **address, addressSpec type,pageState inState,protectType protect)
{
manager->lock();
printf ("Locked in createArea\n");
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
printf ("in area::createArea, base address = %d\n",base);
vpage *newPage;
vnode newVnode;
newVnode.fd=0;
newVnode.offset=0;
for (int i=0;i<pageCount;i++)
{
printf ("in area::createArea, creating page = %d\n",i);
newPage = new vpage(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
vpages.add(newPage);
}
state=inState;
start_address=base;
end_address=base+pageCount*PAGE_SIZE;
manager->unlock();
*address=(void *)base;
printf ("unlocked in createArea\n");
}
void area::freeArea(void)
{
manager->lock();
for (struct node *cur=vpages.rock;cur;cur=cur->next)
{
vpage *page=(vpage *)cur;
page->flush();
delete page; // Probably need to add a destructor
}
manager->unlock();
}
status_t area::getInfo(area_info *dest)
{
// no need to lock here...
strcpy(dest->name,name);
dest->size=end_address-start_address;
dest->lock=state;
@ -98,8 +115,11 @@ status_t area::getInfo(area_info *dest)
bool area::contains(void *address)
{
// no need to lock here...
unsigned long base=(unsigned long)(address);
return ((start_address>=base) && (end_address<=base));
printf ("Inside 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));
}
status_t area::resize(size_t newSize)
@ -109,6 +129,7 @@ status_t area::resize(size_t newSize)
return B_OK;
if (newSize>oldSize)
{
manager->lock();
int pageCount = (newSize-oldSize) / PAGE_SIZE;
vpage *newPage;
vnode newVnode;
@ -123,6 +144,7 @@ status_t area::resize(size_t newSize)
}
else
{
manager->lock();
int pageCount = (oldSize -newSize) / PAGE_SIZE;
vpage *oldPage;
struct node *cur;
@ -133,20 +155,24 @@ status_t area::resize(size_t newSize)
delete oldPage;
}
}
manager->unlock();
}
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();
}
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;
@ -158,6 +184,7 @@ 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);
@ -167,6 +194,7 @@ 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);
@ -176,6 +204,7 @@ 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);
@ -183,6 +212,7 @@ 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)
page->getInt(address);
@ -190,6 +220,7 @@ 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);
@ -197,6 +228,7 @@ 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;
@ -206,6 +238,7 @@ 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;

View File

@ -3,6 +3,7 @@
areaManager::areaManager(void)
{
team=0; // should be proc_get_current_proc_id()
myLock=create_sem(1,"Area Manager Semaphore"); // Should have team name in it.
}
unsigned long areaManager::getNextAddress(int pages, unsigned long start)
@ -39,9 +40,11 @@ area *areaManager::findArea(void *address)
for (struct node *cur=areas.rock;cur;cur=cur->next)
{
area *myArea=(area *)cur;
printf ("Looking for %d\n",address);
if (myArea->contains(address))
return myArea;
}
printf ("findArea is giving up\n");
return NULL;
}

View File

@ -5,6 +5,7 @@ class areaManager // One of these per process
private:
list areas;
team_id team;
sem_id myLock;
public:
areaManager ();
void addArea(area *newArea) {areas.add(newArea);}
@ -16,6 +17,8 @@ class areaManager // One of these per process
area *findArea(area_id id);
void pager(int desperation);
void saver(void);
void lock() {acquire_sem(myLock);}
void unlock() {release_sem(myLock);}
bool fault(void *fault_address, bool writeError); // true = OK, false = panic.

View File

@ -2,6 +2,7 @@
cacheManager::cacheManager(void) : area (NULL)
{
myLock=create_sem(1,"Area Manager Semaphore"); // Should have team name in it.
}
void *cacheManager::findBlock(vnode *target,bool readOnly)
@ -30,10 +31,12 @@ void *cacheManager::createBlock(vnode *target,bool readOnly)
begin+=PAGE_SIZE;
prev=cur;
}
lock();
// Create a vnode here
vpage *newPage = new vpage(begin,*target,NULL,((readOnly)?readable:writable),NO_LOCK);
vpages.add(newPage);
cacheMembers.add(newPage);
unlock();
// return address from this vnode
return (void *)begin;

View File

@ -17,6 +17,7 @@ class cacheManager : public area
// 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);
void *createBlock (vnode *target,bool readOnly);
sem_id myLock;
public:
// For these two, the VFS passes in the target vnode
// Return value is the address. Note that the paging daemon does the actual loading
@ -25,4 +26,6 @@ class cacheManager : public area
void *writeBlock (vnode *target);
void pager(int desperation); // override, as we should blow away useless nodes, not just free blocks.
void saver(void); // Override - not sure why
void lock() {acquire_sem(myLock);}
void unlock() {release_sem(myLock);}
};

View File

@ -19,7 +19,7 @@ class list {
rock=newNode;
nodeCount++;
}
int count(void) {return nodeCount;}
int count(void) {printf ("About to return %d\n",nodeCount);return nodeCount;}
void *next(void) {nodeCount--;node *n=rock;if (rock) rock=rock->next;return rock;}
void remove(void *in)
{
@ -39,7 +39,7 @@ class list {
}
}
struct node *rock;
private:
int nodeCount;
private:
};
#endif

View File

@ -27,20 +27,26 @@ pageManager::pageManager(int pages)
page *pageManager::getPage(void)
{
page *ret=NULL;
// printf ("Checking clean\n");
printf ("Checking clean\n");
printf ("clean = %d\n", &clean);
printf ("cleanCount = %d\n", clean.nodeCount);
if (clean.count())
{
printf ("locking clean\n");
acquire_sem(cleanLock);
printf ("locked clean\n");
ret=(page *)clean.next();
printf ("got next clean\n");
release_sem(cleanLock);
printf ("unlocked clean\n");
} // This could fail if someone swoops in and steal our page.
if (!ret && unused.count())
{
// printf ("Checking unused\n");
printf ("Checking unused\n");
acquire_sem(unusedLock);
ret=(page *)unused.next();
release_sem(unusedLock);
// printf ("ret = %x\n",ret);
printf ("ret = %x\n",ret);
if (ret)
ret->zero();
} // This could fail if someone swoops in and steal our page.

View File

@ -1,25 +1,28 @@
#include "swapFileManager.h"
//#include <stdio.h>
#include <stdio.h>
swapFileManager::swapFileManager(void)
{
swapFile = open("/tmp/OBOS_swap",O_RDWR );
swapFile = open("/boot/var/tmp/OBOS_swap",O_RDWR );
}
void swapFileManager::write_block(vnode node,void *loc,unsigned long size)
{
printf ("writing, node.fd = %d, node.offset = %d\n",node.fd, node.offset);
lseek(node.fd,SEEK_SET,node.offset);
write(node.fd,loc,size);
}
void swapFileManager::read_block(vnode node,void *loc,unsigned long size)
{
printf ("reading, node.fd = %d, node.offset = %d\n",node.fd, node.offset);
lseek(node.fd,SEEK_SET,node.offset);
read(node.fd,loc,size);
}
vnode swapFileManager::findNode(void)
{
printf ("Finding a new node for you master\n");
vnode tmp;
tmp.fd=swapFile;
tmp.offset=maxNode+=PAGE_SIZE; // Can't ever free, swap file grows forever... :-(

View File

@ -5,7 +5,11 @@ int main(int argc,char **argv)
{
vmInterface vm(10);
void *addr;
vm.createArea("Mine",1,&addr);
unsigned long addr;
vm.createArea("Mine",2,(void **)(&addr));
printf ("addr = %d\n",addr);
vm.setByte(addr,99);
printf ("addr = %d\n",addr);
printf ("Byte = %d\n",vm.getByte(addr));
return 0;
}

View File

@ -12,7 +12,7 @@ typedef unsigned long owningProcess;
enum protectType {none=0,readable, writable,copyOnWrite,symCopyOnWrite};
enum pageState {FULL,CONTIGUOUS,LAZY,NO_LOCK,LOMEM};
enum addressSpec {EXACT,BASE,ANY,ANY_KERNEL,CLONE};
#define USER_BASE 0
#define USER_BASE 0x10000000
#define KERNEL_BASE 0x80000000
#define CACHE_BEGIN 0x90000000
#define CACHE_END 0xe0000000

View File

@ -1,10 +1,12 @@
#include "vmInterface.h"
#include "areaManager.h"
//#include "areaManager.h"
#include "mman.h"
areaManager am;
swapFileManager swapMan;
pageManager pageMan(10); // Obviously this hard coded number is a hack...
areaManager *getAM(void)
areaManager *vmInterface::getAM(void)
{
// Normally, we would go to the current user process to get this. Since there no such thing exists here...
return &am;

View File

@ -1,14 +1,14 @@
#include "vm.h"
#include "pageManager.h"
#include "areaManager.h"
#include "swapFileManager.h"
class vmInterface // This is the class that "owns" all of the managers.
{
private:
swapFileManager swapMan;
pageManager pageMan;
int nextAreaID;
areaManager *getAM(void); // This is for testing only...
public:
vmInterface(int pages) : pageMan(pages) {nextAreaID=0;};
vmInterface(int pages) {nextAreaID=0;};
int createArea(char *AreaName,int pageCount,void **address,
addressSpec addType=ANY,
pageState state=NO_LOCK,protectType protect=writable);
@ -27,4 +27,8 @@ class vmInterface // This is the class that "owns" all of the managers.
void pager(void);
void saver(void);
void cleaner(void);
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
void setInt(unsigned long offset,int value) {getAM()->setByte(offset,value);} // This is for testing only
};

View File

@ -1,17 +1,17 @@
#include "vpage.h"
swapFileManager *vpage::swapMan;
pageManager *vpage::pageMan;
extern swapFileManager swapMan;
extern pageManager pageMan;
void vpage::flush(void)
{
if (protection==writable && dirty)
swapMan->write_block(backingNode,physPage, PAGE_SIZE);
swapMan.write_block(backingNode,physPage, PAGE_SIZE);
}
void vpage::refresh(void)
{
swapMan->read_block(backingNode,physPage, PAGE_SIZE);
swapMan.read_block(backingNode,physPage, PAGE_SIZE);
}
vpage *vpage::clone(unsigned long address) // The calling method will have to create this...
@ -29,12 +29,12 @@ vpage::vpage(unsigned long start,vnode backing, page *physMem,protectType prot,p
end_address=start+PAGE_SIZE-1;
protection=prot;
swappable=(state==NO_LOCK);
if (backing.fd=0)
backingNode=swapMan->findNode();
if (backing.fd==0)
backingNode=swapMan.findNode();
else
backingNode=backing;
if (!physPage && (state!=LAZY) && (state!=NO_LOCK))
physPage=pageMan->getPage();
physPage=pageMan.getPage();
else
physPage=physMem;
}
@ -47,6 +47,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 ("Inside fault; address = %d, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
if (writeError)
{
dirty=true;
@ -54,33 +55,41 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa
{
if (protection==copyOnWrite) // Else, this was just a "let me know when I am dirty"...
{
page *newPhysPage=pageMan->getPage();
page *newPhysPage=pageMan.getPage();
memcpy(newPhysPage,physPage,PAGE_SIZE);
physPage=newPhysPage;
protection=writable;
backingNode=swapMan->findNode(); // Need new backing store for this node, since it was copied, the original is no good...
backingNode=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=pageMan->getPage();
physPage=pageMan.getPage();
printf ("New page allocated! address = %s\n",physPage->getAddress());
// Update the architecture specific stuff here...
// This refresh is unneeded if the code was never written out...
refresh(); // I wonder if these vnode calls are safe during an interrupt...
printf ("Refreshed\n");
}
char vpage::getByte(unsigned long address)
{
printf ("inside vpage::getByte; address = %d\n",address );
if (!physPage)
fault((void *)(address),false);
printf ("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)
{
printf ("inside vpage::setByte; address = %d, value = %d\n",address, value);
if (!physPage)
fault((void *)(address),false);
fault((void *)(address),true);
*((char *)(address-start_address+physPage->getAddress()))=value;
printf ("inside vpage::setByte; physical address = %d, value = %d\n",physPage->getAddress(), *((char *)(physPage->getAddress())));
}
int vpage::getInt(unsigned long address)
@ -93,7 +102,7 @@ int vpage::getInt(unsigned long address)
void vpage::setInt(unsigned long address,int value)
{
if (!physPage)
fault((void *)(address),false);
fault((void *)(address),true);
*((int *)(address-start_address+physPage->getAddress()))=value;
}
@ -111,7 +120,7 @@ void vpage::pager(int desperation)
default: return;break;
}
flush();
pageMan->freePage(physPage);
pageMan.freePage(physPage);
physPage=NULL;
}

View File

@ -14,7 +14,7 @@ class vpage : public node
unsigned long end_address;
public:
bool isMapped(void) {return (physPage);}
bool contains(uint32 address) { return ((start_address>=address) && (end_address<=address)); }
bool contains(uint32 address) { return ((start_address<=address) && (end_address>=address)); }
void flush(void); // write page to vnode, if necessary
void refresh(void); // Read page back in from vnode
vpage *clone(unsigned long); // Make a new vpage that is exactly the same as this one.
@ -34,6 +34,4 @@ class vpage : public node
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
static swapFileManager *swapMan;
static pageManager *pageMan;
};