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:
parent
d10f93e702
commit
72515139f7
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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... :-(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user