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:
Michael Phipps 2002-12-17 02:28:39 +00:00
parent 082059d403
commit 8f72c5bcf2
9 changed files with 99 additions and 79 deletions

View File

@ -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 ;

View File

@ -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.

View File

@ -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++;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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;
}
}

View File

@ -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