Make mmap work, more testing, fixed some bad bugs.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@771 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+15
-6
@@ -29,31 +29,40 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque
|
|||||||
break;
|
break;
|
||||||
case CLONE: base=0;break; // Not sure what to do...
|
case CLONE: base=0;break; // Not sure what to do...
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t area::createAreaMappingFile(char *name, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset)
|
status_t area::createAreaMappingFile(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect,int fd,size_t offset)
|
||||||
{
|
{
|
||||||
manager->lock();
|
strcpy(name,inName);
|
||||||
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
|
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
|
||||||
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
|
|
||||||
vpage *newPage;
|
vpage *newPage;
|
||||||
vnode *newVnode=new vnode;
|
|
||||||
|
manager->lock();
|
||||||
|
unsigned long base=mapAddressSpecToAddress(type,requested,pageCount);
|
||||||
for (int i=0;i<pageCount;i++)
|
for (int i=0;i<pageCount;i++)
|
||||||
{
|
{
|
||||||
|
vnode *newVnode=new vnode;
|
||||||
newVnode->fd=fd;
|
newVnode->fd=fd;
|
||||||
newVnode->offset=offset+PAGE_SIZE*i;
|
newVnode->offset=offset+PAGE_SIZE*i;
|
||||||
newPage = new vpage(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
|
newPage = new vpage(base+PAGE_SIZE*i,newVnode,NULL,protect,inState);
|
||||||
vpages.add(newPage);
|
vpages.add(newPage);
|
||||||
|
printf ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset);
|
||||||
}
|
}
|
||||||
|
manager->unlock();
|
||||||
|
|
||||||
state=inState;
|
state=inState;
|
||||||
start_address=base;
|
start_address=base;
|
||||||
end_address=base+pageCount*PAGE_SIZE;
|
end_address=base+pageCount*PAGE_SIZE;
|
||||||
manager->unlock();
|
*address=(void *)base;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t area::createArea(char *name, int pageCount,void **address, addressSpec type,pageState inState,protectType protect)
|
status_t area::createArea(char *inName, int pageCount,void **address, addressSpec type,pageState inState,protectType protect)
|
||||||
{
|
{
|
||||||
|
strcpy(name,inName);
|
||||||
manager->lock();
|
manager->lock();
|
||||||
//printf ("area::createArea: Locked in createArea\n");
|
//printf ("area::createArea: Locked in createArea\n");
|
||||||
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
|
unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works...
|
||||||
|
|||||||
@@ -13,18 +13,20 @@ swapFileManager::swapFileManager(void)
|
|||||||
|
|
||||||
void swapFileManager::write_block(vnode &node,void *loc,unsigned long size)
|
void swapFileManager::write_block(vnode &node,void *loc,unsigned long size)
|
||||||
{
|
{
|
||||||
printf ("swapFileManager::write_block: writing, node.fd = %d, node.offset = %d\n",node.fd, node.offset);
|
printf ("swapFileManager::write_block: writing, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc);
|
||||||
lseek(node.fd,SEEK_SET,node.offset);
|
if (-1==lseek(node.fd,node.offset,SEEK_SET))
|
||||||
write(node.fd,loc,size);
|
printf ("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));
|
||||||
node.valid=true;
|
node.valid=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swapFileManager::read_block(vnode &node,void *loc,unsigned long size)
|
void swapFileManager::read_block(vnode &node,void *loc,unsigned long size)
|
||||||
{
|
{
|
||||||
lseek(node.fd,SEEK_SET,node.offset);
|
lseek(node.fd,node.offset,SEEK_SET);
|
||||||
if (node.valid==false)
|
if (node.valid==false)
|
||||||
return; // Do nothing. This prevents "garbage" data on disk from being read in...
|
return; // Do nothing. This prevents "garbage" data on disk from being read in...
|
||||||
printf ("swapFileManager::read_block: reading, node.fd = %d, node.offset = %d\n",node.fd, node.offset);
|
//printf ("swapFileManager::read_block: reading, node.fd = %d, node.offset = %d\n",node.fd, node.offset);
|
||||||
read(node.fd,loc,size);
|
read(node.fd,loc,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+73
-6
@@ -1,7 +1,11 @@
|
|||||||
#include "vmInterface.h"
|
#include "vmInterface.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <mman.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
vmInterface vm(10);
|
vmInterface vm(20);
|
||||||
|
|
||||||
void writeByte(unsigned long addr,unsigned int offset, char value) { vm.setByte(addr+offset,value); }
|
void writeByte(unsigned long addr,unsigned int offset, char value) { vm.setByte(addr+offset,value); }
|
||||||
|
|
||||||
@@ -37,26 +41,89 @@ int32 loopTest(void *parameters)
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
snooze(params->initialSnooze);
|
snooze(params->initialSnooze);
|
||||||
printf ("Creating %s area\n",params->name);
|
//printf ("Creating %s area\n",params->name);
|
||||||
area1=createFillAndTest(params->areaSize);
|
area1=createFillAndTest(params->areaSize);
|
||||||
snooze(params->holdSnooze);
|
snooze(params->holdSnooze);
|
||||||
|
//printf ("Freeing %s area\n",params->name);
|
||||||
|
vm.freeArea(area1);
|
||||||
|
snooze(params->loopSnooze);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 getInfoTest(void *parameters)
|
||||||
|
{
|
||||||
|
loopTestParameters *params=((loopTestParameters *)parameters);
|
||||||
|
area_info ai;
|
||||||
|
int area1;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
snooze(params->initialSnooze);
|
||||||
|
//printf ("Creating %s area\n",params->name);
|
||||||
|
area1=createFillAndTest(params->areaSize);
|
||||||
|
snooze(params->holdSnooze);
|
||||||
|
|
||||||
|
vm.getAreaInfo(area1,&ai);
|
||||||
|
printf ("Area info : \n");
|
||||||
|
printf ("name : %s\n",ai.name);
|
||||||
|
printf ("size : %d\n",ai.size);
|
||||||
|
printf ("lock : %d\n",ai.lock);
|
||||||
|
printf ("team : %d\n",ai.team);
|
||||||
|
printf ("ram_size : %d\n",ai.ram_size);
|
||||||
|
printf ("in_count : %d\n",ai.in_count);
|
||||||
|
printf ("out_count : %d\n",ai.out_count);
|
||||||
|
printf ("copy_count : %d\n",ai.copy_count);
|
||||||
|
printf ("address : %x\n",ai.address);
|
||||||
|
|
||||||
printf ("Freeing %s area\n",params->name);
|
printf ("Freeing %s area\n",params->name);
|
||||||
vm.freeArea(area1);
|
vm.freeArea(area1);
|
||||||
snooze(params->loopSnooze);
|
snooze(params->loopSnooze);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 mmapTest (void *parameters)
|
||||||
|
{
|
||||||
|
void *map;
|
||||||
|
|
||||||
|
int fd = open ("OBOS_mmap",O_RDWR|O_CREAT,0x777);
|
||||||
|
printf ("Opened file, fd = %d\n",fd);
|
||||||
|
|
||||||
|
loopTestParameters *params=((loopTestParameters *)parameters);
|
||||||
|
int size=params->areaSize; // Note that this is in bytes, not in pages
|
||||||
|
// while (1)
|
||||||
|
{
|
||||||
|
snooze(params->initialSnooze);
|
||||||
|
printf ("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 = %x\n",map);
|
||||||
|
for (int i=0;i<size;i++)
|
||||||
|
writeByte((int32)map,i,i%256);
|
||||||
|
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));
|
||||||
|
snooze(params->loopSnooze);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
printf ("Closed file, fd = %d\n",fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char **argv)
|
int main(int argc,char **argv)
|
||||||
{
|
{
|
||||||
loopTestParameters area1Params={"area1",1000000,2,100000,100000};
|
loopTestParameters area1Params={"area1",1000000,2,100000,100000};
|
||||||
loopTestParameters area2Params={"area2",1000000,2,200000,100000};
|
loopTestParameters area2Params={"area2",1000000,2,200000,100000};
|
||||||
loopTestParameters area3Params={"area3",1000000,2,300000,200000};
|
loopTestParameters area3Params={"area3",1000000,2,300000,200000};
|
||||||
|
loopTestParameters info1Params={"info1",500000,2,400000,30000};
|
||||||
|
loopTestParameters mmap1Params={"mmap",500000,8192,400000,1000000};
|
||||||
|
|
||||||
resume_thread(spawn_thread(loopTest,"area test 1",0,&area1Params));
|
//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 2",0,&area2Params));
|
||||||
resume_thread(spawn_thread(loopTest,"area test 3",0,&area3Params));
|
//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));
|
||||||
|
|
||||||
snooze(50000000);
|
snooze(10000000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,16 +151,18 @@ void *vmInterface::mmap(void *addr, size_t len, int prot, int flags, int fd, off
|
|||||||
// Get the filename from fd...
|
// Get the filename from fd...
|
||||||
strcpy( name,"mmap - need to include fileName");
|
strcpy( name,"mmap - need to include fileName");
|
||||||
|
|
||||||
addressSpec addType=((flags|MAP_FIXED)?EXACT:ANY);
|
addressSpec addType=((flags&MAP_FIXED)?EXACT:ANY);
|
||||||
protectType protType=(prot|PROT_WRITE)?writable:(prot|PROT_READ)?readable:none;
|
protectType protType=(prot&PROT_WRITE)?writable:(prot&PROT_READ)?readable:none;
|
||||||
// Not doing anything with MAP_SHARED and MAP_COPY - needs to be done
|
// Not doing anything with MAP_SHARED and MAP_COPY - needs to be done
|
||||||
if (flags | MAP_ANON)
|
printf ("flags = %x, anon = %x\n",flags,MAP_ANON);
|
||||||
|
if (flags & MAP_ANON)
|
||||||
{
|
{
|
||||||
createArea(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr, addType ,LAZY,protType);
|
createArea(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr, addType ,LAZY,protType);
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
area *newArea = new area(getAM());
|
area *newArea = new area(getAM());
|
||||||
|
printf ("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->createAreaMappingFile(name,(int)((len+PAGE_SIZE-1)/PAGE_SIZE),&addr,addType,LAZY,protType,fd,offset);
|
||||||
newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE
|
newArea->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE
|
||||||
getAM()->addArea(newArea);
|
getAM()->addArea(newArea);
|
||||||
|
|||||||
+13
-9
@@ -6,7 +6,7 @@
|
|||||||
void vpage::flush(void)
|
void vpage::flush(void)
|
||||||
{
|
{
|
||||||
if (protection==writable && dirty)
|
if (protection==writable && dirty)
|
||||||
swapMan.write_block(*backingNode,physPage, PAGE_SIZE);
|
swapMan.write_block(*backingNode,((void *)(physPage->getAddress())), PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpage::refresh(void)
|
void vpage::refresh(void)
|
||||||
@@ -52,7 +52,7 @@ void vpage::setProtection(protectType prot)
|
|||||||
|
|
||||||
bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = panic.
|
bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = panic.
|
||||||
{ // This is dispatched by the real interrupt handler, who locates us
|
{ // This is dispatched by the real interrupt handler, who locates us
|
||||||
//printf ("vpage::fault: address = %d, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
|
printf ("vpage::fault: virtual address = %x, write = %s\n",(unsigned long) fault_address,((writeError)?"true":"false"));
|
||||||
if (writeError)
|
if (writeError)
|
||||||
{
|
{
|
||||||
dirty=true;
|
dirty=true;
|
||||||
@@ -61,7 +61,7 @@ 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"...
|
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);
|
memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),PAGE_SIZE);
|
||||||
physPage=newPhysPage;
|
physPage=newPhysPage;
|
||||||
protection=writable;
|
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...
|
||||||
@@ -71,11 +71,11 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
physPage=pageMan.getPage();
|
physPage=pageMan.getPage();
|
||||||
printf ("vpage::fault: New page allocated! address = %x\n",physPage->getAddress());
|
printf ("vpage::fault: New page allocated! new physical address = %x\n",physPage->getAddress());
|
||||||
// Update the architecture specific stuff here...
|
// Update the architecture specific stuff here...
|
||||||
// This refresh is unneeded if the data was never written out...
|
// This refresh is unneeded if the data was never written out...
|
||||||
refresh(); // I wonder if these vnode calls are safe during an interrupt...
|
refresh(); // I wonder if these vnode calls are safe during an interrupt...
|
||||||
//printf ("vpage::fault: Refreshed\n");
|
printf ("vpage::fault: Refreshed\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,8 @@ char vpage::getByte(unsigned long address)
|
|||||||
{
|
{
|
||||||
// printf ("vpage::getByte: address = %d\n",address );
|
// printf ("vpage::getByte: address = %d\n",address );
|
||||||
if (!physPage)
|
if (!physPage)
|
||||||
fault((void *)(address),false);
|
if (!fault((void *)(address),false))
|
||||||
|
throw ("vpage::getByte",address,0);
|
||||||
// printf ("vpage::getByte: About to return %d\n", *((char *)(address-start_address+physPage->getAddress())));
|
// printf ("vpage::getByte: About to return %d\n", *((char *)(address-start_address+physPage->getAddress())));
|
||||||
return *((char *)(address-start_address+physPage->getAddress()));
|
return *((char *)(address-start_address+physPage->getAddress()));
|
||||||
}
|
}
|
||||||
@@ -92,7 +93,8 @@ void vpage::setByte(unsigned long address,char value)
|
|||||||
{
|
{
|
||||||
// printf ("vpage::setByte: address = %d, value = %d\n",address, value);
|
// printf ("vpage::setByte: address = %d, value = %d\n",address, value);
|
||||||
if (!physPage)
|
if (!physPage)
|
||||||
fault((void *)(address),true);
|
if (!fault((void *)(address),true))
|
||||||
|
throw ("vpage::setByte",address,(int)value);
|
||||||
*((char *)(address-start_address+physPage->getAddress()))=value;
|
*((char *)(address-start_address+physPage->getAddress()))=value;
|
||||||
// printf ("vpage::setByte: physical address = %d, value = %d\n",physPage->getAddress(), *((char *)(physPage->getAddress())));
|
// printf ("vpage::setByte: physical address = %d, value = %d\n",physPage->getAddress(), *((char *)(physPage->getAddress())));
|
||||||
}
|
}
|
||||||
@@ -100,14 +102,16 @@ void vpage::setByte(unsigned long address,char value)
|
|||||||
int vpage::getInt(unsigned long address)
|
int vpage::getInt(unsigned long address)
|
||||||
{
|
{
|
||||||
if (!physPage)
|
if (!physPage)
|
||||||
fault((void *)(address),false);
|
if (!fault((void *)(address),false))
|
||||||
|
throw ("vpage::getInt",address,0);
|
||||||
return *((int *)(address-start_address+physPage->getAddress()));
|
return *((int *)(address-start_address+physPage->getAddress()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void vpage::setInt(unsigned long address,int value)
|
void vpage::setInt(unsigned long address,int value)
|
||||||
{
|
{
|
||||||
if (!physPage)
|
if (!physPage)
|
||||||
fault((void *)(address),true);
|
if (!fault((void *)(address),true))
|
||||||
|
throw ("vpage::setInt",address,value);
|
||||||
*((int *)(address-start_address+physPage->getAddress()))=value;
|
*((int *)(address-start_address+physPage->getAddress()))=value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user