From 53aaaf43d88066b2ab25e96f3a4e8f970d8e1f65 Mon Sep 17 00:00:00 2001 From: Michael Phipps Date: Fri, 16 Aug 2002 01:09:45 +0000 Subject: [PATCH] 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 --- src/kernel/vm2/area.C | 21 ++++++--- src/kernel/vm2/swapFileManager.C | 12 +++-- src/kernel/vm2/test.C | 79 +++++++++++++++++++++++++++++--- src/kernel/vm2/vmInterface.C | 8 ++-- src/kernel/vm2/vpage.C | 22 +++++---- 5 files changed, 113 insertions(+), 29 deletions(-) diff --git a/src/kernel/vm2/area.C b/src/kernel/vm2/area.C index 943e0ef6cf..14a7550755 100644 --- a/src/kernel/vm2/area.C +++ b/src/kernel/vm2/area.C @@ -29,31 +29,40 @@ unsigned long area::mapAddressSpecToAddress(addressSpec type,unsigned long reque break; 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; } -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 base=mapAddressSpecToAddress(type,requested,pageCount); vpage *newPage; - vnode *newVnode=new vnode; + + manager->lock(); + unsigned long base=mapAddressSpecToAddress(type,requested,pageCount); for (int i=0;ifd=fd; newVnode->offset=offset+PAGE_SIZE*i; newPage = new vpage(base+PAGE_SIZE*i,newVnode,NULL,protect,inState); vpages.add(newPage); + printf ("New vnode with fd %d, offset = %d\n",fd,newVnode->offset); } + manager->unlock(); + state=inState; start_address=base; 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(); //printf ("area::createArea: Locked in createArea\n"); unsigned long requested=(unsigned long)(*address); // Hold onto this to make sure that EXACT works... diff --git a/src/kernel/vm2/swapFileManager.C b/src/kernel/vm2/swapFileManager.C index 8f9c119579..cac8f6b945 100644 --- a/src/kernel/vm2/swapFileManager.C +++ b/src/kernel/vm2/swapFileManager.C @@ -13,18 +13,20 @@ swapFileManager::swapFileManager(void) 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); - lseek(node.fd,SEEK_SET,node.offset); - write(node.fd,loc,size); + printf ("swapFileManager::write_block: writing, node.fd = %d, node.offset = %d, address = %x\n",node.fd, node.offset,loc); + if (-1==lseek(node.fd,node.offset,SEEK_SET)) + 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; } 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) 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); } diff --git a/src/kernel/vm2/test.C b/src/kernel/vm2/test.C index c1dadf5115..ca7c654821 100644 --- a/src/kernel/vm2/test.C +++ b/src/kernel/vm2/test.C @@ -1,7 +1,11 @@ #include "vmInterface.h" #include +#include +#include +#include +#include -vmInterface vm(10); +vmInterface vm(20); 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) { snooze(params->initialSnooze); - printf ("Creating %s area\n",params->name); + //printf ("Creating %s area\n",params->name); area1=createFillAndTest(params->areaSize); 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); vm.freeArea(area1); 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;iloopSnooze); + } + close(fd); + printf ("Closed file, fd = %d\n",fd); + } + + int main(int argc,char **argv) { loopTestParameters area1Params={"area1",1000000,2,100000,100000}; loopTestParameters area2Params={"area2",1000000,2,200000,100000}; 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 2",0,&area2Params)); - resume_thread(spawn_thread(loopTest,"area test 3",0,&area3Params)); + //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 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; } diff --git a/src/kernel/vm2/vmInterface.C b/src/kernel/vm2/vmInterface.C index e5d68865a3..5608b70ab7 100644 --- a/src/kernel/vm2/vmInterface.C +++ b/src/kernel/vm2/vmInterface.C @@ -151,16 +151,18 @@ void *vmInterface::mmap(void *addr, size_t len, int prot, int flags, int fd, off // Get the filename from fd... strcpy( name,"mmap - need to include fileName"); - addressSpec addType=((flags|MAP_FIXED)?EXACT:ANY); - protectType protType=(prot|PROT_WRITE)?writable:(prot|PROT_READ)?readable:none; + addressSpec addType=((flags&MAP_FIXED)?EXACT:ANY); + protectType protType=(prot&PROT_WRITE)?writable:(prot&PROT_READ)?readable:none; // 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); return addr; } 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->setAreaID(nextAreaID++); // THIS IS NOT THREAD SAFE getAM()->addArea(newArea); diff --git a/src/kernel/vm2/vpage.C b/src/kernel/vm2/vpage.C index 33ac928fd5..4d6c55fbe7 100644 --- a/src/kernel/vm2/vpage.C +++ b/src/kernel/vm2/vpage.C @@ -6,7 +6,7 @@ void vpage::flush(void) { if (protection==writable && dirty) - swapMan.write_block(*backingNode,physPage, PAGE_SIZE); + swapMan.write_block(*backingNode,((void *)(physPage->getAddress())), PAGE_SIZE); } 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. { // 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) { 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"... { page *newPhysPage=pageMan.getPage(); - memcpy(newPhysPage,physPage,PAGE_SIZE); + memcpy((void *)(newPhysPage->getAddress()),(void *)(physPage->getAddress()),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... @@ -71,11 +71,11 @@ bool vpage::fault(void *fault_address, bool writeError) // true = OK, false = pa } } 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... // This refresh is unneeded if the data was never written out... 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 ); 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()))); 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); if (!physPage) - fault((void *)(address),true); + if (!fault((void *)(address),true)) + throw ("vpage::setByte",address,(int)value); *((char *)(address-start_address+physPage->getAddress()))=value; // 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) { if (!physPage) - fault((void *)(address),false); + if (!fault((void *)(address),false)) + throw ("vpage::getInt",address,0); return *((int *)(address-start_address+physPage->getAddress())); } void vpage::setInt(unsigned long address,int value) { if (!physPage) - fault((void *)(address),true); + if (!fault((void *)(address),true)) + throw ("vpage::setInt",address,value); *((int *)(address-start_address+physPage->getAddress()))=value; }