Fixed a bug in the vnodeManagement
Added statistics counting. Started down the path of making various tests share one VM space. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2265 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
082059d403
commit
8f72c5bcf2
|
@ -2,6 +2,7 @@ SubDir OBOS_TOP src kernel vm2 ;
|
|||
|
||||
BinCommand vmTest : error.C area.C areaManager.C cacheManager.C page.C pageManager.C swapFileManager.C vmInterface.C vpage.C areaPool.C vnodePool.C vpagePool.C vnodeManager.C test.C : root be ;
|
||||
BinCommand simpleTest : error.C area.C areaManager.C cacheManager.C page.C pageManager.C swapFileManager.C vmInterface.C vpage.C areaPool.C vnodePool.C vpagePool.C vnodeManager.C simpleTest.C : root be ;
|
||||
BinCommand testSetup : error.C area.C areaManager.C cacheManager.C page.C pageManager.C swapFileManager.C vmInterface.C vpage.C areaPool.C vnodePool.C vpagePool.C vnodeManager.C simpleTest.C : root be ;
|
||||
BinCommand hashTest : error.C area.C areaManager.C cacheManager.C page.C pageManager.C swapFileManager.C vmInterface.C vpage.C areaPool.C vnodePool.C vpagePool.C vnodeManager.C hashTest.C : root be ;
|
||||
BinCommand olTest : error.C olTest.C : root be ;
|
||||
BinCommand pmTest : error.C pageManager.C pageManTest.C page.C : root be ;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
1) Must lock original area when clone()ing. Sigh. Also must add ability to clone other process' areas. The issue here is that areaManager is finding the areas. Need to keep a global list of areas for this. An area might well work.
|
||||
2) Add statistics counting for copy in/out
|
||||
3) Tests are not done.
|
||||
1) Change the architecture so that instead of multiple threads of tests, we have multiple apps of tests...
|
||||
2) Tests are not done.
|
||||
Test:
|
||||
getNextAreaInfo
|
||||
cloneArea
|
||||
|
@ -9,10 +8,7 @@
|
|||
mmap / munmap
|
||||
paging
|
||||
disk caching
|
||||
4) Change the architecture so that instead of multiple threads of tests, we have multiple apps of tests...
|
||||
|
||||
5) Need to make the paging daemon load the pages in, using semaphores.
|
||||
-- Looks like we *don't* have to do this, based on what is done in NewOS. Need to consult...
|
||||
6) See how unresolvable page faults and permissions errors are handled - need to properly handle
|
||||
4) 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.
|
||||
5) There is no arch-level integration. This is to be tested (to death) in user land first. * == can not be done in user land.
|
||||
|
|
|
@ -95,6 +95,7 @@ status_t area::createAreaGuts( char *inName, int pageCount, void **address, addr
|
|||
base+=PAGE_SIZE;
|
||||
}
|
||||
dump();
|
||||
vmBlock->areas.add(this);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -152,16 +153,13 @@ status_t area::getInfo(area_info *dest) {
|
|||
dest->protection=protection;
|
||||
dest->team=manager->getTeam();
|
||||
dest->ram_size=0;
|
||||
dest->in_count=0;
|
||||
dest->out_count=0;
|
||||
dest->in_count=in_count;
|
||||
dest->out_count=out_count;
|
||||
dest->copy_count=0;
|
||||
for (hashIterate hi(vpages);node *cur=hi.get();) {
|
||||
vpage *page=(vpage *)cur;
|
||||
if (page->isMapped())
|
||||
dest->ram_size+=PAGE_SIZE;
|
||||
dest->in_count+=PAGE_SIZE;
|
||||
dest->out_count+=PAGE_SIZE;
|
||||
dest->copy_count+=PAGE_SIZE;
|
||||
}
|
||||
dest->address=(void *)start_address;
|
||||
return B_OK;
|
||||
|
@ -234,7 +232,7 @@ vpage *area::findVPage(unsigned long address) {
|
|||
bool area::fault(void *fault_address, bool writeError) { // true = OK, false = panic.
|
||||
vpage *page=findVPage((unsigned long)fault_address);
|
||||
if (page)
|
||||
return page->fault(fault_address,writeError);
|
||||
return page->fault(fault_address,writeError,in_count);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
@ -271,7 +269,8 @@ void area::setInt(unsigned long address,int value) { // This is for testing only
|
|||
void area::pager(int desperation) {
|
||||
for (hashIterate hi(vpages);node *cur=hi.get();) {
|
||||
vpage *page=(vpage *)cur;
|
||||
page->pager(desperation);
|
||||
if (page->pager(desperation))
|
||||
out_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,14 +5,12 @@
|
|||
#include "areaPool.h"
|
||||
extern vmHeaderBlock *vmBlock;
|
||||
|
||||
bool areaIsLessThan(void *a,void *b)
|
||||
{
|
||||
bool areaIsLessThan(void *a,void *b) {
|
||||
return (((reinterpret_cast<area *>(a))->getStartAddress()) < (reinterpret_cast<area *>(b))->getStartAddress());
|
||||
}
|
||||
|
||||
// This creates the one true lock for this area
|
||||
areaManager::areaManager(void)
|
||||
{
|
||||
areaManager::areaManager(void) {
|
||||
team=0; // should be proc_get_current_proc_id()
|
||||
myLock=0;
|
||||
myLock=create_sem(1,"Area Manager Semaphore"); // Should have team name in it.
|
||||
|
@ -20,8 +18,7 @@ areaManager::areaManager(void)
|
|||
}
|
||||
|
||||
// Loops over every area looking for someplace where we can get the space we need.
|
||||
unsigned long areaManager::getNextAddress(int pages, unsigned long start)
|
||||
{
|
||||
unsigned long areaManager::getNextAddress(int pages, unsigned long start) {
|
||||
// This function needs to deal with the possibility that we run out of address space...
|
||||
// areas.dump();
|
||||
unsigned long end=start+(pages*PAGE_SIZE)-1;
|
||||
|
@ -42,8 +39,7 @@ unsigned long areaManager::getNextAddress(int pages, unsigned long start)
|
|||
}
|
||||
|
||||
// Remove the area from our list, put it on the area pool and move on
|
||||
void areaManager::freeArea(area_id areaID)
|
||||
{
|
||||
void areaManager::freeArea(area_id areaID) {
|
||||
error ("areaManager::freeArea: begin\n");
|
||||
lock();
|
||||
area *oldArea=findArea(areaID);
|
||||
|
@ -54,6 +50,7 @@ void areaManager::freeArea(area_id areaID)
|
|||
// error ("areaManager::freeArea: areaManager = %x \n",manager);
|
||||
removeArea(oldArea);
|
||||
// error ("areaManager::freeArea: deleting area %x \n",oldArea);
|
||||
vmBlock->areas.remove(oldArea);
|
||||
oldArea->freeArea();
|
||||
// error ("areaManager::freeArea: freeArea complete \n");
|
||||
vmBlock->areaPool->put(oldArea);
|
||||
|
@ -63,8 +60,7 @@ void areaManager::freeArea(area_id areaID)
|
|||
unlock();
|
||||
}
|
||||
|
||||
area *areaManager::findAreaLock(void *address)
|
||||
{
|
||||
area *areaManager::findAreaLock(void *address) {
|
||||
lock();
|
||||
area *retVal=findArea(address);
|
||||
unlock();
|
||||
|
@ -72,8 +68,7 @@ area *areaManager::findAreaLock(void *address)
|
|||
}
|
||||
|
||||
// Loops over our areas looking for this one by name
|
||||
area *areaManager::findArea(char *address)
|
||||
{
|
||||
area *areaManager::findArea(char *address) {
|
||||
error ("Finding area by string\n");
|
||||
area *retVal=NULL;
|
||||
lock();
|
||||
|
@ -88,8 +83,7 @@ area *areaManager::findArea(char *address)
|
|||
}
|
||||
|
||||
// Loops over our areas looking for the one whose virtual address matches the passed in address
|
||||
area *areaManager::findArea(void *address)
|
||||
{
|
||||
area *areaManager::findArea(void *address) {
|
||||
// THIS DOES NOT HAVE LOCKING - all callers must lock.
|
||||
// error ("Finding area by void * address\n");
|
||||
for (struct node *cur=areas.rock;cur;cur=cur->next)
|
||||
|
@ -103,8 +97,7 @@ area *areaManager::findArea(void *address)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
area *areaManager::findAreaLock(area_id id)
|
||||
{
|
||||
area *areaManager::findAreaLock(area_id id) {
|
||||
error ("Finding area by areaID \n");
|
||||
lock();
|
||||
area *retVal=findArea(id);
|
||||
|
@ -113,8 +106,7 @@ area *areaManager::findAreaLock(area_id id)
|
|||
}
|
||||
|
||||
// Loops over our areas looking for the one whose ID was passed in
|
||||
area *areaManager::findArea(area_id id)
|
||||
{
|
||||
area *areaManager::findArea(area_id id) {
|
||||
//error ("Finding area by area_id\n");
|
||||
area *retVal=NULL;
|
||||
for (struct node *cur=areas.rock;cur && !retVal;cur=cur->next)
|
||||
|
@ -127,8 +119,7 @@ area *areaManager::findArea(area_id id)
|
|||
}
|
||||
|
||||
// Find the area whose address matches this page fault and dispatch the fault to it.
|
||||
bool areaManager::fault(void *fault_address, bool writeError) // true = OK, false = panic.
|
||||
{
|
||||
bool areaManager::fault(void *fault_address, bool writeError) { // true = OK, false = panic.
|
||||
area *myArea;
|
||||
bool retVal;
|
||||
error ("Faulting \n");
|
||||
|
@ -145,8 +136,7 @@ bool areaManager::fault(void *fault_address, bool writeError) // true = OK, fals
|
|||
long areaManager::nextAreaID=0;
|
||||
|
||||
// Create an area; get a new structure, call setup, create the guts, set its ID, add it to our list
|
||||
int areaManager::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect)
|
||||
{
|
||||
int areaManager::createArea(char *AreaName,int pageCount,void **address, addressSpec addType,pageState state,protectType protect) {
|
||||
error ("areaManager::createArea - Creating an area\n");
|
||||
lock();
|
||||
area *newArea = new (vmBlock->areaPool->get()) area;
|
||||
|
@ -167,14 +157,24 @@ int areaManager::createArea(char *AreaName,int pageCount,void **address, address
|
|||
return retVal;
|
||||
}
|
||||
|
||||
area *findAreaGlobal(int areaID) {
|
||||
for (struct node *cur=vmBlock->areas.rock;cur;cur=cur->next) {
|
||||
area *myArea=(area *)cur;
|
||||
if (((area *)(cur))->getAreaID()==areaID)
|
||||
return myArea;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// FIX: THIS IS WRONG! It will only clone areas in our areaManager.
|
||||
// Should: find the specified area, create a new area to be its clone, and set it up
|
||||
int areaManager::cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType,pageState state,protectType protect)
|
||||
{
|
||||
int areaManager::cloneArea(int newAreaID,char *AreaName,void **address, addressSpec addType,pageState state,protectType protect) {
|
||||
int retVal;
|
||||
error ("Cloning an area\n");
|
||||
lock();
|
||||
area *oldArea=findArea(newAreaID);
|
||||
if (!oldArea)
|
||||
oldArea=findAreaGlobal(newAreaID);
|
||||
if (oldArea)
|
||||
{
|
||||
area *newArea = new (vmBlock->areaPool->get()) area;
|
||||
|
@ -191,8 +191,7 @@ int areaManager::cloneArea(int newAreaID,char *AreaName,void **address, addressS
|
|||
return retVal;
|
||||
}
|
||||
|
||||
char areaManager::getByte(unsigned long address)
|
||||
{
|
||||
char areaManager::getByte(unsigned long address) {
|
||||
area *myArea;
|
||||
// error ("areaManager::getByte : starting\n");
|
||||
int retVal;
|
||||
|
@ -210,8 +209,7 @@ char areaManager::getByte(unsigned long address)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
int areaManager::getInt(unsigned long address)
|
||||
{
|
||||
int areaManager::getInt(unsigned long address) {
|
||||
area *myArea;
|
||||
int retVal;
|
||||
lock();
|
||||
|
@ -228,8 +226,7 @@ int areaManager::getInt(unsigned long address)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
void areaManager::setByte(unsigned long address,char value)
|
||||
{
|
||||
void areaManager::setByte(unsigned long address,char value) {
|
||||
// error ("areaManager::setByte : starting\n");
|
||||
area *myArea;
|
||||
lock();
|
||||
|
@ -245,15 +242,13 @@ void areaManager::setByte(unsigned long address,char value)
|
|||
unlock();
|
||||
}
|
||||
|
||||
void areaManager::setInt(unsigned long address,int value)
|
||||
{
|
||||
void areaManager::setInt(unsigned long address,int value) {
|
||||
area *myArea;
|
||||
lock();
|
||||
myArea=findArea((void *)address);
|
||||
if (myArea)
|
||||
myArea->setInt(address,value);
|
||||
else
|
||||
{
|
||||
else {
|
||||
char temp[1000];
|
||||
sprintf (temp,"Unable to find an area for address %d\n",address);
|
||||
throw (temp);
|
||||
|
@ -262,11 +257,9 @@ void areaManager::setInt(unsigned long address,int value)
|
|||
}
|
||||
|
||||
// Call pager for each of our areas
|
||||
void areaManager::pager(int desperation)
|
||||
{
|
||||
void areaManager::pager(int desperation) {
|
||||
lock();
|
||||
for (struct node *cur=areas.rock;cur;cur=cur->next)
|
||||
{
|
||||
for (struct node *cur=areas.rock;cur;cur=cur->next) {
|
||||
area *myArea=(area *)cur;
|
||||
//error ("areaManager::pager; area = \n");
|
||||
//myArea->dump();
|
||||
|
@ -276,11 +269,9 @@ void areaManager::pager(int desperation)
|
|||
}
|
||||
|
||||
// Call saver for each of our areas
|
||||
void areaManager::saver(void)
|
||||
{
|
||||
void areaManager::saver(void) {
|
||||
lock();
|
||||
for (struct node *cur=areas.rock;cur;cur=cur->next)
|
||||
{
|
||||
for (struct node *cur=areas.rock;cur;cur=cur->next) {
|
||||
area *myArea=(area *)cur;
|
||||
myArea->saver();
|
||||
}
|
||||
|
@ -288,8 +279,7 @@ void areaManager::saver(void)
|
|||
}
|
||||
|
||||
// mmap is basically map POSIX values to ours and call createAreaMappingFile...
|
||||
void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) {
|
||||
char name[MAXPATHLEN];
|
||||
// Get the filename from fd...
|
||||
strcpy( name,"mmap - need to include fileName");
|
||||
|
@ -299,8 +289,7 @@ void *areaManager::mmap(void *addr, size_t len, int prot, int flags, int fd, off
|
|||
// Not doing anything with MAP_SHARED and MAP_COPY - needs to be done
|
||||
//error ("flags = %x, anon = %x\n",flags,MAP_ANON);
|
||||
lock();
|
||||
if (flags & MAP_ANON)
|
||||
{
|
||||
if (flags & MAP_ANON) {
|
||||
createArea(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr, addType ,LAZY,protType);
|
||||
return addr;
|
||||
}
|
||||
|
@ -326,14 +315,12 @@ status_t areaManager::munmap(void *addr,size_t len)
|
|||
status_t retVal=B_OK;
|
||||
lock();
|
||||
area *myArea=findArea(addr);
|
||||
if (myArea)
|
||||
{
|
||||
if (myArea) {
|
||||
removeArea(myArea);
|
||||
myArea->freeArea();
|
||||
vmBlock->areaPool->put(myArea);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
error ("areaManager::munmap: unable to find requested area\n");
|
||||
retVal=B_ERROR;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#include "vmInterface.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <mman.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
vmInterface *vm;
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
try {
|
||||
vm = new vmInterface (30);
|
||||
|
||||
while (1)
|
||||
snooze(1000000);
|
||||
}
|
||||
catch (const char *t)
|
||||
{
|
||||
error ("Exception thrown! %s\n",t);
|
||||
exit(1);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
error ("Unknown Exception thrown!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -18,7 +18,7 @@ struct vnode : public node
|
|||
}
|
||||
};
|
||||
#define B_OS_NAME_LENGTH 32
|
||||
enum protectType {none=0,readable, writable,copyOnWrite,symCopyOnWrite};
|
||||
enum protectType {none=0,readable, writable,copyOnWrite};
|
||||
//B_EXACT_ADDRESS You want the value of *addr to be taken literally and strictly.
|
||||
// If the area can't be allocated at that location, the function fails.
|
||||
//B_BASE_ADDRESS The area can start at a location equal to or greater than *addr.
|
||||
|
|
|
@ -10,6 +10,7 @@ class pageManager;
|
|||
class swapFileManager;
|
||||
class cacheManager;
|
||||
class vnodeManager;
|
||||
class list;
|
||||
#endif
|
||||
|
||||
struct vmHeaderBlock
|
||||
|
@ -21,6 +22,7 @@ struct vmHeaderBlock
|
|||
swapFileManager *swapMan;
|
||||
cacheManager *cacheMan;
|
||||
vnodeManager *vnodeMan;
|
||||
list areas;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -102,7 +102,7 @@ void vpage::setProtection(protectType prot) {
|
|||
|
||||
// This is dispatched by the real interrupt handler, who locates us
|
||||
// true = OK, false = panic.
|
||||
bool vpage::fault(void *fault_address, bool writeError) {
|
||||
bool vpage::fault(void *fault_address, bool writeError, int &in_count) {
|
||||
error ("vpage::fault: virtual address = %lx, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
|
||||
if (writeError && physPage) { // If we already have a page and this is a write, it is either a copy on write or a "dirty" notice
|
||||
dirty=true;
|
||||
|
@ -112,7 +112,9 @@ bool vpage::fault(void *fault_address, bool writeError) {
|
|||
memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE);
|
||||
physPage=newPhysPage;
|
||||
protection=writable;
|
||||
vmBlock->vnodeMan->remove(*backingNode,*this);
|
||||
backingNode=&(vmBlock->swapMan->findNode()); // Need new backing store for this node, since it was copied, the original is no good...
|
||||
vmBlock->vnodeMan->addVnode(backingNode,*this);
|
||||
// Update the architecture specific stuff here...
|
||||
}
|
||||
return true;
|
||||
|
@ -128,6 +130,7 @@ bool vpage::fault(void *fault_address, bool writeError) {
|
|||
dump();
|
||||
refresh(); // I wonder if these vnode calls are safe during an interrupt...
|
||||
dirty=false;
|
||||
in_count++;
|
||||
error ("vpage::fault: Refreshed\n");
|
||||
dump();
|
||||
error ("vpage::fault: exiting\n");
|
||||
|
@ -170,18 +173,18 @@ void vpage::setInt(unsigned long address,int value,areaManager *manager) {
|
|||
}
|
||||
|
||||
// Swaps pages out where necessary.
|
||||
void vpage::pager(int desperation) {
|
||||
bool vpage::pager(int desperation) {
|
||||
//error ("vpage::pager start desperation = %d\n",desperation);
|
||||
if (!swappable)
|
||||
return;
|
||||
return false;
|
||||
error ("vpage::pager swappable\n");
|
||||
switch (desperation) {
|
||||
case 1: return; break;
|
||||
case 2: if (!physPage || protection!=readable) return;break;
|
||||
case 3: if (!physPage || dirty) return;break;
|
||||
case 4: if (!physPage) return;break;
|
||||
case 5: if (!physPage) return;break;
|
||||
default: return;break;
|
||||
case 1: return false; break;
|
||||
case 2: if (!physPage || protection!=readable) return false;break;
|
||||
case 3: if (!physPage || dirty) return false;break;
|
||||
case 4: if (!physPage) return false;break;
|
||||
case 5: if (!physPage) return false;break;
|
||||
default: return false;break;
|
||||
}
|
||||
error ("vpage::pager flushing\n");
|
||||
flush();
|
||||
|
@ -189,11 +192,13 @@ void vpage::pager(int desperation) {
|
|||
vmBlock->pageMan->freePage(physPage);
|
||||
error ("vpage::pager going to NULL\n");
|
||||
physPage=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Saves dirty pages
|
||||
void vpage::saver(void) {
|
||||
if (dirty)
|
||||
if (dirty) {
|
||||
flush();
|
||||
dirty=false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@ class vpage : public node
|
|||
bool contains(uint32 address) { return ((start_address<=address) && (end_address>=address)); }
|
||||
|
||||
// External methods for "server" type calls
|
||||
bool fault(void *fault_address, bool writeError); // true = OK, false = panic.
|
||||
void pager(int desperation);
|
||||
bool fault(void *fault_address, bool writeError, int &in_count); // true = OK, false = panic.
|
||||
bool pager(int desperation);
|
||||
void saver(void);
|
||||
|
||||
// Debugging
|
||||
|
|
Loading…
Reference in New Issue